Newtonsoft Json Serializer / Deserializer - how to use shared objects instead of JObject?
I have a JSON specified with a reassuring service that I am consuming that looks like this:
{
"id": "97",
"name": "Tom Production",
"description": null,
"parameters": [
{
"first_parameter_name": "First Parameter Value"
},
{
"second_parameter_name": "Second Parameter Value"
}
]
}
Note that property IDs, name, description and parameters are listed as part of the specification. The collection of generic parameters shown in my example as "first_parameter_name" and "second_parameter_name" is not specified .... it could be anything and I want to map them to typed objects.
I declared an object for this as:
[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; }
}
Serialization works fine as expected:
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);
gives the JSON I'm looking for just like the one at the top of this post.
HOWEVER.
Deserialization does NOT work fine. If it worked the way I hope it would be creating generic types like I did and the following code should work ... but instead it throws a reflection exception:
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));
}
}
Instead, I need to write Newtonsoft (ick) specific code to use some sort of Newtonsoft fake reflection:
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);
}
}
}
Is there a way I can control the Deserializer so that it generates the correct generic types and not the JObject type using JProperties?
Thank you very much in advance.
source to share
JObject
s match most directly to Dictionary<string, object>
s , since each is a set of keys to values. If you know the value is always equal string
, you can do it 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);
}
}
source to share