有没有一种方法可以将JSON内容反序列化为C#动态类型? 能够跳过创建大量的类以使用DataContractJsonSerializer
将是很好的。
有没有一种方法可以将JSON内容反序列化为C#动态类型? 能够跳过创建大量的类以使用DataContractJsonSerializer
将是很好的。
使用 Json.NET 很简单:
dynamic stuff = JsonConvert.DeserializeObject("{ 'Name': 'Jon Smith', 'Address': { 'City': 'New York', 'State': 'NY' }, 'Age': 42 }");
string name = stuff.Name;
string address = stuff.Address.City;
还有使用 Newtonsoft.Json.Linq
:
dynamic stuff = JObject.Parse("{ 'Name': 'Jon Smith', 'Address': { 'City': 'New York', 'State': 'NY' }, 'Age': 42 }");
string name = stuff.Name;
string address = stuff.Address.City;
文档: 使用动态方式查询JSON
stuff
,可以这样做:foreach (Newtonsoft.Json.Linq.JProperty jproperty in stuff) { Console.WriteLine("jproperty.Name = {0}", jproperty.Name);}
。 - Matthiasasync
方法内部。如果我将该方法改为同步方法,则可以按预期正常工作。但是,如果将该方法更改为 async
,我无法获得一个 dynamic
,而只能获得一个 object
。明确转换也没有用,仍然只会给我一个 object
。还有其他人遇到这个问题吗? - codeConcussion如果您愿意依赖于 System.Web.Helpers 程序集,那么您可以使用 Json 类:Json
dynamic data = Json.Decode(json);
它作为MVC框架的一个附加组件包含在.NET 4框架中。如果这有帮助,一定要给Vlad点个赞!但是,如果您不能假设客户端环境包括此DLL,请继续阅读。
这里提供了另一种反序列化方法 (点击跳转)。我稍微修改了代码以修复一个错误并适应我的编程风格。您只需要这段代码和对System.Web.Extensions
的引用即可:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Dynamic;
using System.Linq;
using System.Text;
using System.Web.Script.Serialization;
public sealed class DynamicJsonConverter : JavaScriptConverter
{
public override object Deserialize(IDictionary<string, object> dictionary, Type type, JavaScriptSerializer serializer)
{
if (dictionary == null)
throw new ArgumentNullException("dictionary");
return type == typeof(object) ? new DynamicJsonObject(dictionary) : null;
}
public override IDictionary<string, object> Serialize(object obj, JavaScriptSerializer serializer)
{
throw new NotImplementedException();
}
public override IEnumerable<Type> SupportedTypes
{
get { return new ReadOnlyCollection<Type>(new List<Type>(new[] { typeof(object) })); }
}
#region Nested type: DynamicJsonObject
private sealed class DynamicJsonObject : DynamicObject
{
private readonly IDictionary<string, object> _dictionary;
public DynamicJsonObject(IDictionary<string, object> dictionary)
{
if (dictionary == null)
throw new ArgumentNullException("dictionary");
_dictionary = dictionary;
}
public override string ToString()
{
var sb = new StringBuilder("{");
ToString(sb);
return sb.ToString();
}
private void ToString(StringBuilder sb)
{
var firstInDictionary = true;
foreach (var pair in _dictionary)
{
if (!firstInDictionary)
sb.Append(",");
firstInDictionary = false;
var value = pair.Value;
var name = pair.Key;
if (value is string)
{
sb.AppendFormat("{0}:\"{1}\"", name, value);
}
else if (value is IDictionary<string, object>)
{
new DynamicJsonObject((IDictionary<string, object>)value).ToString(sb);
}
else if (value is ArrayList)
{
sb.Append(name + ":[");
var firstInArray = true;
foreach (var arrayValue in (ArrayList)value)
{
if (!firstInArray)
sb.Append(",");
firstInArray = false;
if (arrayValue is IDictionary<string, object>)
new DynamicJsonObject((IDictionary<string, object>)arrayValue).ToString(sb);
else if (arrayValue is string)
sb.AppendFormat("\"{0}\"", arrayValue);
else
sb.AppendFormat("{0}", arrayValue);
}
sb.Append("]");
}
else
{
sb.AppendFormat("{0}:{1}", name, value);
}
}
sb.Append("}");
}
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
if (!_dictionary.TryGetValue(binder.Name, out result))
{
// return null to avoid exception. caller can check for null this way...
result = null;
return true;
}
result = WrapResultObject(result);
return true;
}
public override bool TryGetIndex(GetIndexBinder binder, object[] indexes, out object result)
{
if (indexes.Length == 1 && indexes[0] != null)
{
if (!_dictionary.TryGetValue(indexes[0].ToString(), out result))
{
// return null to avoid exception. caller can check for null this way...
result = null;
return true;
}
result = WrapResultObject(result);
return true;
}
return base.TryGetIndex(binder, indexes, out result);
}
private static object WrapResultObject(object result)
{
var dictionary = result as IDictionary<string, object>;
if (dictionary != null)
return new DynamicJsonObject(dictionary);
var arrayList = result as ArrayList;
if (arrayList != null && arrayList.Count > 0)
{
return arrayList[0] is IDictionary<string, object>
? new List<object>(arrayList.Cast<IDictionary<string, object>>().Select(x => new DynamicJsonObject(x)))
: new List<object>(arrayList.Cast<object>());
}
return result;
}
}
#endregion
}
你可以像这样使用它:
string json = ...;
var serializer = new JavaScriptSerializer();
serializer.RegisterConverters(new[] { new DynamicJsonConverter() });
dynamic obj = serializer.Deserialize(json, typeof(object));
因此,考虑到一个 JSON 字符串:
{
"Items":[
{ "Name":"Apple", "Price":12.3 },
{ "Name":"Grape", "Price":3.21 }
],
"Date":"21/11/2010"
}
以下代码将在运行时起作用:dynamic data = serializer.Deserialize(json, typeof(object));
data.Date; // "21/11/2010"
data.Items.Count; // 2
data.Items[0].Name; // "Apple"
data.Items[0].Price; // 12.3 (as a decimal)
data.Items[1].Name; // "Grape"
data.Items[1].Price; // 3.21 (as a decimal)
params
(这是 C# 中的关键字)。除了 TryGetMember
,您还可以重写 TryGetIndex
,它会给您与 JS 中完全相同的行为。然后您就可以使用 obj["params"]
或 obj["background-color"]
来处理尴尬的字段名。 - Martin Endervar dynamicObject = Json.Decode(jsonString);
将简单的“字符串 JSON 数据”转换为对象,无需使用任何第三方 DLL 文件:
WebClient client = new WebClient();
string getString = client.DownloadString("https://graph.facebook.com/zuck");
JavaScriptSerializer serializer = new JavaScriptSerializer();
dynamic item = serializer.Deserialize<object>(getString);
string name = item["name"];
//note: JavaScriptSerializer in this namespaces
//System.Web.Script.Serialization.JavaScriptSerializer
注意:您也可以使用自定义对象。
Personel item = serializer.Deserialize<Personel>(getString);
myObject["myprop"]
访问反序列化对象的动态性吗?我知道这是在运行时完成的,但是通过 myObject["myprop"]
访问它是有效的吗? - Royi Namir.NET 4.0内置了一个库可以实现这个功能:
using System.Web.Script.Serialization;
JavaScriptSerializer jss = new JavaScriptSerializer();
var d = jss.Deserialize<dynamic>(str);
这是最简单的方法。
Dictionary<string,object>
。除非我漏掉了什么,你的例子并没有返回一个动态对象。 - sergiopereiraIDynamicMetaObjectProvider
(或使用例如ExpandoObject
)来拦截属性并在内部字典中查找它们。 这与使用 dynamic
结合使用,使得可以使用 d.code
等代码。 把字典强制转换为动态类型有点毫无意义。 - Stephen Drewusing Newtonsoft.Json;
dynamic results = JsonConvert.DeserializeObject<dynamic>(YOUR_JSON);
我来这里是为了找到一个关于.NET Core的答案,不使用任何第三方或额外的参考资料。如果你使用标准JsonSerializer
类和ExpandoObject
一起使用,它可以正常工作。以下是对我有效的示例:
using System.Text.Json;
using System.Dynamic;
dynamic json = JsonSerializer.Deserialize<ExpandoObject>(jsonText);
Console.WriteLine(json.name);
这段代码会打印出传入Deserialize
方法的JSON文本中存在的name
属性的字符串值。完美 - 没有额外的库,什么都没有。只是 .NET Core。
编辑:可能对于包含嵌套元素的多级JSON存在问题。对于单层平面对象有效。
ExpandoObject
是昂贵的! - Mazdak ShojaieJsonFx可以将JSON内容反序列化为动态对象。
将数据序列化/反序列化为动态类型(在.NET 4.0中默认):
var reader = new JsonReader(); var writer = new JsonWriter();
string input = @"{ ""foo"": true, ""array"": [ 42, false, ""Hello!"", null ] }";
dynamic output = reader.Read(input);
Console.WriteLine(output.array[0]); // 42
string json = writer.Write(output);
Console.WriteLine(json); // {"foo":true,"array":[42,false,"Hello!",null]}
还有一种方法是使用Newtonsoft.Json:
dynamic stuff = Newtonsoft.Json.JsonConvert.DeserializeObject("{ color: 'red', value: 5 }");
string color = stuff.color;
int value = stuff.value;
我制作了一个使用Expando Objects的DynamicJsonConverter新版本。我使用expando对象,因为我想要使用Json.NET将动态内容序列化回JSON。
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Dynamic;
using System.Web.Script.Serialization;
public static class DynamicJson
{
public static dynamic Parse(string json)
{
JavaScriptSerializer jss = new JavaScriptSerializer();
jss.RegisterConverters(new JavaScriptConverter[] { new DynamicJsonConverter() });
dynamic glossaryEntry = jss.Deserialize(json, typeof(object)) as dynamic;
return glossaryEntry;
}
class DynamicJsonConverter : JavaScriptConverter
{
public override object Deserialize(IDictionary<string, object> dictionary, Type type, JavaScriptSerializer serializer)
{
if (dictionary == null)
throw new ArgumentNullException("dictionary");
var result = ToExpando(dictionary);
return type == typeof(object) ? result : null;
}
private static ExpandoObject ToExpando(IDictionary<string, object> dictionary)
{
var result = new ExpandoObject();
var dic = result as IDictionary<String, object>;
foreach (var item in dictionary)
{
var valueAsDic = item.Value as IDictionary<string, object>;
if (valueAsDic != null)
{
dic.Add(item.Key, ToExpando(valueAsDic));
continue;
}
var arrayList = item.Value as ArrayList;
if (arrayList != null && arrayList.Count > 0)
{
dic.Add(item.Key, ToExpando(arrayList));
continue;
}
dic.Add(item.Key, item.Value);
}
return result;
}
private static ArrayList ToExpando(ArrayList obj)
{
ArrayList result = new ArrayList();
foreach (var item in obj)
{
var valueAsDic = item as IDictionary<string, object>;
if (valueAsDic != null)
{
result.Add(ToExpando(valueAsDic));
continue;
}
var arrayList = item as ArrayList;
if (arrayList != null && arrayList.Count > 0)
{
result.Add(ToExpando(arrayList));
continue;
}
result.Add(item);
}
return result;
}
public override IDictionary<string, object> Serialize(object obj, JavaScriptSerializer serializer)
{
throw new NotImplementedException();
}
public override IEnumerable<Type> SupportedTypes
{
get { return new ReadOnlyCollection<Type>(new List<Type>(new[] { typeof(object) })); }
}
}
}