Newtonsoft Json Serializer/Deserializer - 如何使用通用对象而不是 JObject?
Newtonsoft Json Serializer/Deserializer - how to use generic objects instead of JObject?
我有 JSON 由我正在使用的 restful 服务指定,例如:
{
"id": "97",
"name": "Tom Production",
"description": null,
"parameters": [
{
"first_parameter_name": "First Parameter Value"
},
{
"second_parameter_name": "Second Parameter Value"
}
]
}
请注意,属性 名称 id、名称、描述和参数都是作为规范的一部分建立的。通用参数的集合,在我的示例中显示为 "first_parameter_name" 和 "second_parameter_name" 未指定....可以是任何东西,我想将它们映射到通用类型的对象。
我为此声明了一个对象:
[DataContract (Name = "MyClass")]
public class MyClass
{
[DataMember (Name = "id")]
public string Id { get; set; }
[DataMember(Name = "name")]
public string Name { get; set; }
[DataMember(Name = "description")]
public string Description { get; set; }
[DataMember(Name = "parameters")]
public List<object> Parameters { get; set; }
}
序列化工作正常,完全符合我的预期:
var myObject = new MyClass();
myObject.Id = "97";
myObject.Name = "Tom Production";
myObject.Parameters = new List<object>();
myObject.Parameters.Add(new { first_parameter_name = "First Parameter Value" });
myObject.Parameters.Add(new { second_parameter_name = "Second Parameter Value" });
string json = JsonConvert.SerializeObject(myObject);
Console.WriteLine(json);
产生了我正在寻找的 JSON,与这篇文章的顶部完全一样。
但是。
反序列化无法正常工作。如果它按照我希望的方式工作,那就是创建泛型类型,就像我创建的那样,下面的代码应该可以工作....但它会抛出一个反射异常:
var myNewObject = JsonConvert.DeserializeObject<MyClass>(json);
foreach (object o in myNewObject.Parameters)
{
Type t = o.GetType();
Console.WriteLine("\tType is {0}", t);
foreach (PropertyInfo pi in t.GetProperties(BindingFlags.Instance | BindingFlags.Public))
{
Console.WriteLine("\t\tName is {0}", pi.Name);
Console.WriteLine("\t\tValue is {0}", pi.GetValue(o, null));
}
}
相反,我必须编写特定于 Newtonsoft (ick) 的代码来使用一种伪造的 Newtonsoft 反射:
var myNewObject = JsonConvert.DeserializeObject<MyClass>(json);
foreach (object o in myNewObject.Parameters)
{
var jo = o as JObject;
if (jo != null)
{
foreach (JProperty prop in jo.Properties())
{
Console.WriteLine("\t\tName is {0}", prop.Name);
Console.WriteLine("\t\tValue is {0}", prop.Value);
}
}
}
有没有一种方法可以控制反序列化器,使其生成正确的泛型类型而不是带有 JProperties 的 JObject 类型?
非常感谢。
JObject
s map most directly to Dictionary<string, object>
s,因为它们只是键值的集合。如果您知道该值始终是 string
,则可以将其设为 Dictionary<string, string>
。
[DataMember(Name = "parameters")]
public List<Dictionary<string, object>> Parameters { get; set; }
// or
[DataMember(Name = "parameters")]
public List<Dictionary<string, string>> Parameters { get; set; }
// e.g.
var myNewObject = JsonConvert.DeserializeObject<MyClass>(json);
foreach (var dict in myNewObject.Parameters)
{
foreach (var pair in dict)
{
Console.WriteLine("\t\tKey is {0}", pair.Key);
Console.WriteLine("\t\tValue is {0}", pair.Value);
}
}
我有 JSON 由我正在使用的 restful 服务指定,例如:
{
"id": "97",
"name": "Tom Production",
"description": null,
"parameters": [
{
"first_parameter_name": "First Parameter Value"
},
{
"second_parameter_name": "Second Parameter Value"
}
]
}
请注意,属性 名称 id、名称、描述和参数都是作为规范的一部分建立的。通用参数的集合,在我的示例中显示为 "first_parameter_name" 和 "second_parameter_name" 未指定....可以是任何东西,我想将它们映射到通用类型的对象。
我为此声明了一个对象:
[DataContract (Name = "MyClass")]
public class MyClass
{
[DataMember (Name = "id")]
public string Id { get; set; }
[DataMember(Name = "name")]
public string Name { get; set; }
[DataMember(Name = "description")]
public string Description { get; set; }
[DataMember(Name = "parameters")]
public List<object> Parameters { get; set; }
}
序列化工作正常,完全符合我的预期:
var myObject = new MyClass();
myObject.Id = "97";
myObject.Name = "Tom Production";
myObject.Parameters = new List<object>();
myObject.Parameters.Add(new { first_parameter_name = "First Parameter Value" });
myObject.Parameters.Add(new { second_parameter_name = "Second Parameter Value" });
string json = JsonConvert.SerializeObject(myObject);
Console.WriteLine(json);
产生了我正在寻找的 JSON,与这篇文章的顶部完全一样。
但是。
反序列化无法正常工作。如果它按照我希望的方式工作,那就是创建泛型类型,就像我创建的那样,下面的代码应该可以工作....但它会抛出一个反射异常:
var myNewObject = JsonConvert.DeserializeObject<MyClass>(json);
foreach (object o in myNewObject.Parameters)
{
Type t = o.GetType();
Console.WriteLine("\tType is {0}", t);
foreach (PropertyInfo pi in t.GetProperties(BindingFlags.Instance | BindingFlags.Public))
{
Console.WriteLine("\t\tName is {0}", pi.Name);
Console.WriteLine("\t\tValue is {0}", pi.GetValue(o, null));
}
}
相反,我必须编写特定于 Newtonsoft (ick) 的代码来使用一种伪造的 Newtonsoft 反射:
var myNewObject = JsonConvert.DeserializeObject<MyClass>(json);
foreach (object o in myNewObject.Parameters)
{
var jo = o as JObject;
if (jo != null)
{
foreach (JProperty prop in jo.Properties())
{
Console.WriteLine("\t\tName is {0}", prop.Name);
Console.WriteLine("\t\tValue is {0}", prop.Value);
}
}
}
有没有一种方法可以控制反序列化器,使其生成正确的泛型类型而不是带有 JProperties 的 JObject 类型?
非常感谢。
JObject
s map most directly to Dictionary<string, object>
s,因为它们只是键值的集合。如果您知道该值始终是 string
,则可以将其设为 Dictionary<string, string>
。
[DataMember(Name = "parameters")]
public List<Dictionary<string, object>> Parameters { get; set; }
// or
[DataMember(Name = "parameters")]
public List<Dictionary<string, string>> Parameters { get; set; }
// e.g.
var myNewObject = JsonConvert.DeserializeObject<MyClass>(json);
foreach (var dict in myNewObject.Parameters)
{
foreach (var pair in dict)
{
Console.WriteLine("\t\tKey is {0}", pair.Key);
Console.WriteLine("\t\tValue is {0}", pair.Value);
}
}