如何在 asp.net mvc 中展平通过 JsonResult 返回的 ExpandoObject?
我真的很喜欢在运行时编译服务器端动态对象时使用 ExpandoObject
,但在 JSON 序列化过程中我无法将其展平。首先,我实例化该对象:
dynamic expando = new ExpandoObject();
var d = expando as IDictionary<string, object>;
expando.Add("SomeProp", SomeValueOrClass);
到目前为止一切顺利。在我的 MVC 控制器中,我想将其作为 JsonResult 发送下来,所以我这样做:
return new JsonResult(expando);
这会将 JSON 序列化为下面的内容,以供浏览器使用:
[{"Key":"SomeProp", "Value": SomeValueOrClass}]
但是,我真正想要的是看到这个:
{SomeProp: SomeValueOrClass}
我知道如果我使用dynamic
而不是ExpandoObject
我可以实现这个目标 - JsonResult
能够序列化动态
属性和值到单个对象中(没有Key或Value业务),但我需要使用ExpandoObject
的原因是因为我不知道所有我想要在运行时之前在对象上添加属性,据我所知,如果不使用 ExpandoObject
,我无法动态地将属性添加到 dynamic
中。
我可能必须在 JavaScript 中筛选“键”、“值”业务,但我希望在将其发送给客户端之前弄清楚这一点。感谢您的帮助!
I really like the ExpandoObject
while compiling a server-side dynamic object at runtime, but I am having trouble flattening this thing out during JSON serialization. First, I instantiate the object:
dynamic expando = new ExpandoObject();
var d = expando as IDictionary<string, object>;
expando.Add("SomeProp", SomeValueOrClass);
So far so good. In my MVC controller, I want to then send this down as a JsonResult, so I do this:
return new JsonResult(expando);
This serializes the JSON into the below, to be consumed by the browser:
[{"Key":"SomeProp", "Value": SomeValueOrClass}]
BUT, what I'd really like is to see this:
{SomeProp: SomeValueOrClass}
I know I can achieve this if I use dynamic
instead of ExpandoObject
-- JsonResult
is able to serialize the dynamic
properties and values into a single object (with no Key or Value business), but the reason I need to use ExpandoObject
is because I don't know all of the properties I want on the object until runtime, and as far as I know, I cannot dynamically add a property to a dynamic
without using an ExpandoObject
.
I may have to sift through the "Key", "Value" business in my javascript, but I was hoping to figure this out prior to sending it to the client. Thanks for your help!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(12)
使用 JSON.NET,您可以调用 SerializeObject 来“展平”expando 对象:
将输出:
在 ASP.NET MVC 控制器的上下文中,可以使用 Content-method 返回结果:
Using JSON.NET you can call SerializeObject to "flatten" the expando object:
Will output:
In the context of an ASP.NET MVC Controller, the result can be returned using the Content-method:
您还可以制作一个仅适用于 ExpandoObject 的特殊 JSONConverter,然后将其注册到 JavaScriptSerializer 的实例中。这样你就可以序列化expando数组,expando对象的组合......直到你找到另一种没有正确序列化的对象(“你想要的方式”),然后你创建另一个转换器,或者添加另一种类型这个。希望这有帮助。
使用转换器
You could also, make a special JSONConverter that works only for ExpandoObject and then register it in an instance of JavaScriptSerializer. This way you could serialize arrays of expando,combinations of expando objects and ... until you find another kind of object that is not getting serialized correctly("the way u want"), then you make another Converter, or add another type to this one. Hope this helps.
Using converter
以下是我为实现您所描述的行为所做的操作:
代价是您在序列化数据之前要复制数据。
Here's what I did to achieve the behavior you're describing:
The cost is that you're making a copy of the data before serializing it.
我通过编写一个将 ExpandoObject 转换为 JSON 字符串的扩展方法解决了这个问题:
这使用了优秀的 Newtonsoft 库。
然后 JsonResult 看起来像这样:
这将返回到浏览器:
我可以通过这样做在 javascript 中使用它(引用 这里):
我希望这有帮助!
I solved this by writing an extension method that converts the ExpandoObject into a JSON string:
This uses the excellent Newtonsoft library.
JsonResult then looks like this:
And this is returned to the browser:
And I can use it in javascript by doing this (referenced here):
I hope this helps!
我能够使用 JsonFx 解决同样的问题。
输出:
I was able to solve this same problem using JsonFx.
output:
我进一步进行了扁平化过程并检查了列表对象,这消除了无意义的键值。 :)
I took the flattening process one step further and checked for list objects, which removes the key value nonsense. :)
JsonResult
使用JavaScriptSerializer
,它实际上根据需要反序列化(具体)Dictionary
。Dictionary
构造函数有一个重载,它采用IDictionary
。ExpandoObject
实现IDictionary
(我想你可以看到我要去的地方...)单级 ExpandoObject
一行代码,使用所有内置类型:)
嵌套 ExpandoObjects
当然,如果您嵌套
ExpandoObject
那么您需要将它们全部递归地转换为Dictionarys:
你的最终代码变成
JsonResult
usesJavaScriptSerializer
which actually deserializes (the concrete)Dictionary<string, object>
as you want.There's an overload of the
Dictionary<string, object>
constructor which takesIDictionary<string, object>
.ExpandoObject
implementsIDictionary<string, object>
(I think you can see where I am going here...)Single level ExpandoObject
One line of code, using all built-in types :)
Nested ExpandoObjects
Of course if you are nesting
ExpandoObject
s then you will need to recursively convert them all intoDictionary<string, object>
s:your final code becoming
这可能对你没有用,但我有类似的要求,但使用 SerializedDynamicObject
我将字典的名称更改为“Fields”,然后使用 Json.Net 序列化以生成如下所示的 json:
{"Fields": {“属性1”:“值1”,“属性2”:“值2”等。
其中 Property1 和 Property2 是动态添加的属性 - 即字典键
如果我能够摆脱封装其余部分的额外“Fields”属性,那就太完美了,但我已经解决了这个限制。
答案移自 此问题
This may not be useful to you, but I had a similar requirement, but used a SerializableDynamicObject
I changed the name of the dictionary to "Fields" and then this serializes with Json.Net to produce json which looks like:
{"Fields":{"Property1":"Value1", "Property2":"Value2" etc.
where Property1 and Property2 are Dynamically added properties - i.e. Dictionary Keys
It would be perfect if I could get rid of the extra "Fields" property which encapsulates the rest, but I've worked around that limitation.
Answer moved from this question on request
这是一个迟到的答案,但我也遇到了同样的问题,这个问题帮助我解决了这些问题。
作为总结,我认为我应该发布我的结果,希望它能加快其他人的实施速度。
首先是 ExpandoJsonResult,您可以在操作中返回它的实例。或者您可以重写控制器中的 Json 方法并将其返回那里。
然后是转换器(它支持序列化和反序列化。请参阅下面的示例了解如何反序列化)。
您可以在 ExpandoJsonResult 类中看到如何使用它进行序列化。要反序列化,请以相同的方式创建序列化器并注册转换器,但要使用
非常感谢这里所有帮助我的参与者。
This is a late answer, but I had the same problem, and this question helped me solve them.
As a summary, I thought I should post my results, in hopes that it speeds up the implementation for others.
First the ExpandoJsonResult, which you can return an instance of in your action. Or you can override the Json method in your controller and return it there.
Then the converter (which supports both serialization and de-serialization. See below for an example of how to de-serialize).
You can see in the ExpandoJsonResult class how to use it for serialization. To de-serialize, create the serializer and register the converter in the same way, but use
A big thank you, to all participants here that helped me.
使用从 ASP.Net 4 中的 WebApi 返回动态 ExpandoObject,默认的 JSON 格式化程序似乎将 ExpandoObject 扁平化为简单的 JSON 对象。
Using returning dynamic ExpandoObject from WebApi in ASP.Net 4, the default JSON formatter seems to flatten ExpandoObjects into simple JSON object.
序列化程序似乎正在将 Expando 转换为字典,然后对其进行序列化(因此是键/值业务)。您是否尝试过反序列化为字典,然后将其转换回 Expando?
It seems like the serializer is casting the Expando to a Dictionary and then serializing it (thus the Key/Value business). Have you tried Deserializing as a Dictionary and then casting that back to an Expando?
我刚刚遇到了同样的问题并发现了一些非常奇怪的事情。
如果我这样做:
它有效,但前提是我的方法使用 HttpPost 属性。如果我使用 HttpGet 我会收到错误。
所以我的答案仅适用于 HttpPost。就我而言,这是一个 Ajax 调用,因此我可以通过 HttpPost 更改 HttpGet。
I just had the same problem and figured out something pretty weird.
If I do:
It works, but only if my method use HttpPost attribute. If I use HttpGet i get error.
So my answer works only on HttpPost. In my case it was an Ajax Call so i could change HttpGet by HttpPost.