Deserialize JSON dictionary-like to object with properties - c#

I'm stuck with an awful API which returns the following JSON:
{
"root":[
{
"row":[
{
"name":"Foo",
"value":"Some value"
},
{
"name":"Bar",
"value":"Some other value"
}, (...)
]
},
{
"row":[
{
"name":"Foo",
"value":"Lorem"
},
{
"name":"Bar",
"value":"Ipsum"
}, (...)
]
}, (...)
]
}
I'd like to use Newtonsoft.Json to deserialize it as a List of C# objects, so that name will match object property and value will be property value. The class would look like this:
class Row
{
public string Foo { get; set; }
public string Bar { get; set; }
(...)
}
Any ideas?

You can use a custom JsonConverter to handle this. Below a simple example that requires some null checks etc, but this gets the idea:
public class RowConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return objectType == typeof(Row[]);
}
public override bool CanWrite => false;
public override bool CanRead => true;
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.Null)
{
return string.Empty;
}
else if (reader.TokenType == JsonToken.String)
{
return serializer.Deserialize(reader, objectType);
}
else
{
JObject obj = JObject.Load(reader);
var root = obj["root"];
if (root != null)
{
var rows = new List<Row>();
foreach (var item in root)
{
var row = item["row"];
var newRow = new Row();
foreach(var field in row)
{
// better use reflection here to convert name-value to property setter
if (field.Value<string>("name") == "Foo")
{
newRow.Foo = field["value"].Value<string>();
}
if (field.Value<string>("name") == "Bar")
{
newRow.Bar = field["value"].Value<string>();
}
}
rows.Add(newRow);
}
return rows.ToArray();
}
return null;
}
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
Then on your Row class:
[JsonConverter(typeof(RowConverter))]
public class Row
{
public string Foo { get; set; }
public string Bar { get; set; }
}
If you need to include it in your MVC, in Startup.cs (asp.net core):
services
.AddMvc()
.AddJsonOptions(options => { options.SerializerSettings.Converters.Add(new RowConverter()); });

As an option you can convert it to dictionary for your single "row" property:
var values = JsonConvert.DeserializeObject<Dictionary<string, string>>(json);
And after create dynamic object:
private static dynamic DictionaryToObject(IDictionary<String, Object> dictionary)
{
var expandoObj = new ExpandoObject();
var expandoObjCollection = (ICollection<KeyValuePair<String, Object>>)expandoObj;
foreach (var keyValuePair in dictionary)
{
expandoObjCollection.Add(keyValuePair);
}
dynamic eoDynamic = expandoObj;
return eoDynamic;
}
private static T DictionaryToObject<T>(IDictionary<String, Object> dictionary) where T : class
{
return DictionaryToObject(dictionary) as T;
}

You can make classes like below then use newtosnsoft
public class root
{
public List<row> row {get;set;}
}
public class row
{
public string name {get;set;}
public string value {get;set;}
}

Related

Is there a way to return a custom JSON structure on an object when using System.Text.Json?

I am writing a class (AttributeBag) that doesn't expose any public properties. Inside, I have a list of objects (Attribute) that I manage via Get and Set methods. I want to be able to run JsonSerializer.Serialize() on the AttributeBag class and retrieve a JSON structure like below:
[
{
"Name": "x",
"Value": "y"
},
{
"Name": "x1",
"Value": "y1"
},
{
"Name": "x2",
"Value": "y2"
}
]
My Attribute and AttributeBag classes look like these:
public class Attribute
{
public string Name { get; set; }
public object Value { get; set; }
}
public class AttributeBag
{
private readonly List<Attribute> attributes;
public AttributeBag()
{
this.attributes = new List<Attribute>();
}
public AttributeBag Set(string name, object value)
{
var searchAttribute = this.attributes.Find(x => x.Name.Equals(name));
if (searchAttribute != null)
{
searchAttribute.Value = value;
}
else
{
this.attributes.Add(new Attribute { Name = name, Value = value });
}
return this;
}
public Attribute Get(string name)
{
var searchAttribute = this.attributes.Find(x => x.Name.Equals(name));
if (searchAttribute != null)
{
return searchAttribute;
}
else
{
throw new AttributeNameNotFoundException(name);
}
}
public object GetValue(string name)
{
var searchAttribute = this.attributes.Find(x => x.Name.Equals(name));
if (searchAttribute != null)
{
return searchAttribute.Value;
}
else
{
throw new AttributeNameNotFoundException(name);
}
}
}
I want to be able to do something simple like this:
var ab = new AttributeBag();
ab.Set("x", "y");
ab.Set("x1", "y1");
ab.Set("x2", "y2");
string jsonData = JsonSerializer.Serialize(ab);
I tried looking at the documentation but unsure of how to proceed with the above. Should I be using Utf8JsonWriter for this? It seems that if I use Utf8JsonWriter I would need to have a function that implements the JSON Writing and call it with ab.Serialize() for example and wouldn't need to use JsonSerializer directly. Would that be the way to go or is there a way to use JsonSerializer.Serialize?
Any pointers would be much appreciated!
Thanks to Sushant Yelpale for the hint and link in the comments, I managed to implement the custom serialization as below.
I created a new converter class AttributeBagConverter:
class AttributeBagConverter : JsonConverter<AttributeBag>
{
public override bool CanConvert(Type typeToConvert)
{
return true;
}
public override AttributeBag Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
throw new NotImplementedException();
}
public override void Write(Utf8JsonWriter writer, AttributeBag value, JsonSerializerOptions options)
{
writer.WriteStartArray();
if (value.Count > 0)
{
foreach (var item in value)
{
writer.WriteStartObject();
writer.WritePropertyName("Name");
writer.WriteStringValue(item.Name);
writer.WritePropertyName("Value");
if (double.TryParse(item.Value.ToString(), out double n))
{
writer.WriteNumberValue(n);
}
else
{
writer.WriteStringValue(item.Value.ToString());
}
writer.WriteEndObject();
}
}
writer.WriteEndArray();
writer.Flush();
}
}
Then I decorated my AttributeBag class with JsonConverter(typeof(AttributeBagConverter)):
[JsonConverter(typeof(AttributeBagConverter))]
public class AttributeBag: IEnumerable<Attribute>
{
private readonly List<Attribute> attributes;
public int Count
{
get
{
return this.attributes.Count;
}
}
public AttributeBag()
{
this.attributes = new List<Attribute>();
}
public AttributeBag Set(string name, object value)
{
var searchAttribute = this.attributes.Find(x => x.Name.Equals(name));
if (searchAttribute != null)
{
searchAttribute.Value = value;
}
else
{
this.attributes.Add(new Attribute { Name = name, Value = value });
}
return this;
}
public Attribute Get(string name)
{
var searchAttribute = this.attributes.Find(x => x.Name.Equals(name));
if (searchAttribute != null)
{
return searchAttribute;
}
else
{
throw new AttributeNameNotFoundException(name);
}
}
public object GetValue(string name)
{
var searchAttribute = this.attributes.Find(x => x.Name.Equals(name));
if (searchAttribute != null)
{
return searchAttribute.Value;
}
else
{
throw new AttributeNameNotFoundException(name);
}
}
public IEnumerator<Attribute> GetEnumerator()
{
return this.attributes.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
Calling JsonSerializer.Serialize() on the object now returns the correct JSON format that I was looking for!
If you are using Newtonsoft.Json you may use custom JsonConverter like this
using Newtonsoft.Json;
using System.Collections.Generic;
[JsonConverter(typeof(AttributeBagConverter))]
public class AttributeBag
{
//private constructor to make it able to create instance from converter
private AttributeBag(List<Attribute> attributes)
{
this.attributes = attributes;
}
public class AttributeBagConverter : JsonConverter<AttributeBag>
{
public override AttributeBag ReadJson(JsonReader reader, System.Type objectType,
AttributeBag existingValue, bool hasExistingValue, JsonSerializer serializer)
{
//deserialize as List<Attribute> and pass results to private constructor
return new AttributeBag(serializer.Deserialize<List<Attribute>>(reader));
}
public override void WriteJson(JsonWriter writer, AttributeBag value,
JsonSerializer serializer)
{
//serialize List<Attribute> only
serializer.Serialize(writer, value.attributes);
}
}
/* rest of your code */
}
as you can see it's serialize and deserialize you object in the way you want

How to Serialize and Deserialize ArrayList of Arrays by using Json.NET

I need to serialize/deserialize an object to json by using JSON.NET in my application. Object has a property type of ArrayList which contains string arrays. To simulate it I've written the following unit test;
public class JsonTests
{
public class MyTestClass
{
public ArrayList Items { get; private set; }
public MyTestClass()
{
this.Items = new ArrayList();
}
}
[Fact]
public void JsonConvert_Should_Serialize_ArrayList_And_Deserialize_Successfully()
{
MyTestClass myObject = new MyTestClass();
myObject.Items.Add(new string[] { "Test1", "Test2" });
string jsonResult = JsonConvert.SerializeObject(myObject);
MyTestClass tempMyObject = JsonConvert.DeserializeObject<MyTestClass>(jsonResult);
//(tempMyObject.Items[0] as string[]) casts to null therefore it throws exception
Assert.Equal((myObject.Items[0] as string[])[0], (tempMyObject.Items[0] as string[])[0]);
}
}
It does not throw any exception durion serialization. However, it does not deserialize ArrayList properly.
My question is , how can I deserialize it back to ArrayList of string arrays ?
Update: In addition, I cannot change the class definition. The class is implemented in an assembly where I cannot edit the class.
ArrayList is a non-generic, untyped collection so you need to inform Json.NET of the expected type of the items. One way to do this is with a custom JsonConverter for the ArrayList:
public class ArrayListConverter<TItem> : JsonConverter
{
public override bool CanWrite { get { return false; } }
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.Null)
return null;
var list = serializer.Deserialize<List<TItem>>(reader);
var arrayList = existingValue as ArrayList ?? new ArrayList(list.Count);
arrayList.AddRange(list);
return arrayList;
}
public override bool CanConvert(Type objectType)
{
return objectType == typeof(ArrayList);
}
}
Then apply the converter to the class as follows:
public class MyTestClass
{
[JsonConverter(typeof(ArrayListConverter<string []>))]
public ArrayList Items { get; private set; }
public MyTestClass()
{
this.Items = new ArrayList();
}
}
Sample fiddle.
If the class cannot be modified, and you want all instances of ArrayList in your object graph to deserialize their items as string [], you can add the converter to JsonSerializerSettings.Converters instead of adding it to the type:
var tempMyObject = JsonConvert.DeserializeObject<MyTestClass>(jsonResult,
new JsonSerializerSettings { Converters = { new ArrayListConverter<string []>() } });
Sample fiddle #2.
And finally, if the class cannot be modified and you only want the specific ArrayList Items property inside MyTestClass to have its items deserialized as string [], you will need to create a custom converter for MyTestClass. You can use the pattern from Custom deserializer only for some fields with json.NET to custom-deserialize the ArrayList property while populating the remainder with default deserialization:
public class MyTestClassConverter : JsonConverter
{
public override bool CanWrite { get { return false; } }
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.Null)
return null;
var root = existingValue as MyTestClass ?? (MyTestClass)serializer.ContractResolver.ResolveContract(objectType).DefaultCreator();
var jsonObject = JObject.Load(reader);
var jsonItems = jsonObject["Items"].RemoveFromLowestPossibleParent();
if (jsonItems != null && jsonItems.Type != JTokenType.Null)
{
root.Items.AddRange(jsonItems.ToObject<List<string []>>());
}
// Populate the remaining standard properties
using (var subReader = jsonObject.CreateReader())
{
serializer.Populate(subReader, root);
}
return root;
}
public override bool CanConvert(Type objectType)
{
return typeof(MyTestClass).IsAssignableFrom(objectType);
}
}
public static class JsonExtensions
{
public static JToken RemoveFromLowestPossibleParent(this JToken node)
{
if (node == null)
return null;
var contained = node.AncestorsAndSelf().Where(t => t.Parent is JContainer && t.Parent.Type != JTokenType.Property).FirstOrDefault();
if (contained != null)
contained.Remove();
// Also detach the node from its immediate containing property -- Remove() does not do this even though it seems like it should
if (node.Parent is JProperty)
((JProperty)node.Parent).Value = null;
return node;
}
}
Then use it as follows:
var tempMyObject = JsonConvert.DeserializeObject<MyTestClass>(jsonResult,
new JsonSerializerSettings { Converters = { new MyTestClassConverter() } });
Sample fiddle #3.
Try this I hope this code help you
using List and JSON.NET
List<string[]> list = new List<string[]>();
list.Add(new string[] { "Value","value" });
list.Add(new string[] { "b2", "b22" });
var ee = JsonConvert.SerializeObject(list);
Console.WriteLine(ee);
List<string[]> ll = JsonConvert.DeserializeObject<List<string[]>>(ee);
foreach (var Valus in ll)
{
foreach (var val in Valus)
{
Console.WriteLine(val);
}
}
using Array List
string[][] strarry = { new string[] { "f1", "f2", "f3" }, new string[] { "s1", "s2", "s3" }, new string[] { "t1", "t2", "t3" } };
string SerializeArray = json.Serialize(strarry);
string[][] DeSerializeArrayList = json.Deserialize<string[][]>(SerializeArray);
foreach (var item in DeSerializeArrayList)
{
foreach (var Subitem in item)
{
Response.Write(Subitem + "<br/>");
}
}
using List
List<Data> list = new List<Data>();
list.Add(new Data() { ID = 1, Name = "val1" });
list.Add(new Data() { ID = 2, Name = "val2" });
JavaScriptSerializer json = new JavaScriptSerializer();
string Serialize = json.Serialize(list);
Response.Write(Serialize);
List<Data> DeSerialize = json.Deserialize<List<Data>>(Serialize);
foreach (var Data in DeSerialize)
{
Response.Write(Data.Name);
}
Data Class
public class Data
{
public int ID { get; set; }
public string Name { get; set; }
}

How to deserialize an array of an array of objects using Newtonsoft

I am trying to deserialize an Object like this.
My issue is that it is blowing up trying to deserialize the inner items.
{
"outeritems": [{
"inneritems": [
[{
"itemid": "1"
}, {
"itemid": "2"
}]
]
}]
}
I have already tried
public List<List<inneritems>> inneritems{ get; set; }
also
public List<inneritems> inneritems{ get; set; }
I'm thinking this might have to have a custom JSON converter
Actually vikas is close in anwering your question.
public class Outeritem
{
public List<List<object>> inneritems { get; set; }
}
public class RootValue
{
public List<Outeritem> outeritems { get; set; }
}
[TestMethod]
public void SerializeAndDeserializeTest()
{
var expected = "{\"outeritems\":[{\"inneritems\":[[{\"itemid\":\"1\"},{\"itemid\":\"2\"}]]}]}";
var rootValue = new RootValue
{
outeritems = new List<Outeritem>
{
new Outeritem
{
inneritems = new List<List<object>> {
new List<object> { new {itemid = "1"},new {itemid = "2"} }
}
}
}
};
var actual = JsonConvert.SerializeObject(rootValue);
Assert.AreEqual(expected, actual);
}
Try this
public class Inneritem
{
public String itemid { get; set; }
}
public class Outeritem
{
public List<Inneritem> inneritems { get; set; }
}
public class RootValue
{
public List<Outeritem> outeritems { get; set; }
}
I had to create a custom Newtonsoft JSON Converter
This is what I did.
Created A JsonCreationConverter Base Class
public abstract class JsonCreationConverter<T> : JsonConverter
{
protected abstract T Create(Type objectType, JObject jObject);
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException("Unnecessary because CanWrite is false. The type will skip the converter.");
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.Null)
return null;
JObject jObject = JObject.Load(reader);
T target = Create(objectType, jObject);
// Populate the object properties
serializer.Populate(jObject.CreateReader(), target);
return target;
}
public override bool CanConvert(Type objectType)
{
return typeof(T).IsAssignableFrom(objectType);
}
public override bool CanWrite
{
get { return false; }
}
}
Created A Costume Converter that inherited my base class
public class OuterConverter :
JsonCreationConverter<OuterItems>
{
protected override OuterItems Create(Type objectType, JObject jObject)
{
OuterItems outeritems =
new OuterItems();
var properties = jObject.Properties().ToList();
outeritems.InnerItems = GetInnerItems((object)properties[0].Value);
return outeritems;
}
// Need to iterate through list so creating a custom object
private List<List<InnerItems>> GetInnerItems(object propertyValue)
{
string sinneritems = "";
object inneritems = propertyValue;
sinneritems = String.Format("{0}", inneritems);
sinneritems = sinneritems.Insert(1, "{ \"Items\": [");
sinneritems = sinneritems.Substring(1, sinneritems.Length - 1);
sinneritems = sinneritems.Remove(sinneritems.Length - 1);
sinneritems += "]}";
dynamic results = JObject.Parse(sinneritems);
List<List<InnerItems>> innerItemsList = new List<List<InnerItems>>();
List<InnerItems> linnerItems = new List<InnerItems>();
foreach (var items in results.Items)
{
foreach (var item in items)
{
string sItem = String.Format("{0}", item);
InnerItems ninneritems = Newtonsoft.Json.JsonConvert.DeserializeObject<InnerItems>(sItem);
linnerItems.Add(ninneritems);
}
innerItemsList.Add(linnerItems);
}
return innerItemsList;
}
}
Append the New Converter on the Newtonsoft Deserializer
return Newtonsoft.Json.JsonConvert.DeserializeObject<T>(result.ToString(),
new OuterConverter());

Deserialize JSON as object or array with JSON.Net [duplicate]

This question already has answers here:
How to handle both a single item and an array for the same property using JSON.net
(9 answers)
Closed 3 years ago.
I want to know if it is possible to deserialize a JSON object that could either be an object or an array.
Similar to this question: Jackson deserialize object or array
But using JSON.Net.
Example
{
"response": {
"status":"success",
// Could be either a single object or an array of objects.
"data": {
"prop":"value"
}
// OR
"data": [
{"prop":"value"},
{"prop":"value"}
]
}
}
I think this solves your problem
string jsonString= "your json string";
var token = JToken.Parse(jsonString);
if (token is JArray)
{
IEnumerable<Car> cars= token.ToObject<List<Car>>();
}
else if (token is JObject)
{
Car car= token.ToObject<Car>();
}
An alternative would be to write our JsonConverter and use it for deserializing so we can work with static types after conversion.
class JsonDataConverter : JsonConverter
{
public override bool CanWrite { get { return false; } }
public override bool CanConvert(Type objectType)
{
return objectType == typeof(Data);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var token = JToken.ReadFrom(reader);
if (token is JArray)
return new Data(token.Select(t => t["prop"].ToString()));
if (token is JObject)
return new Data(new[] { token["prop"].ToString() });
throw new NotSupportedException();
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
[JsonConverter(typeof(JsonDataConverter))]
class Data:List<string>
{
public Data() : base() { }
public Data(IEnumerable<string> data) : base(data) { }
}
class Response
{
public string Status { get; set; }
public Data Data { get; set; }
}
and an example:
class Program
{
static void Main(string[] args)
{
var inputObj = #"{
'response': {
'status':'success',
// Could be either a single object or an array of objects.
'data': { 'prop':'value'}
}
}";
var inputArray = #"{
'response': {
'status':'success',
// Could be either a single object or an array of objects.
'data':[
{ 'prop':'value'},
{ 'prop':'value'}
]
}
}";
var obj = JsonConvert.DeserializeAnonymousType(inputObj, new { Response = new Response() });
foreach(var prop in obj.Response.Data)
Console.WriteLine(prop);
var arr = JsonConvert.DeserializeAnonymousType(inputArray, new { Response = new Response() });
foreach (var prop in arr.Response.Data)
Console.WriteLine(prop);
}
}
You can change the property type for "data" in your model to dynamic or an object and check if it is an array on run-time.
Here's an example:
public class Response
{
[JsonProperty("status")]
public string Status { get; set; }
[JsonProperty("data")]
public dynamic Data { get; set; }
}
var response = JsonConvert.DeserializeJson<Response>(json);
.
.
.
Type responseDataType = response.Data.GetType();
if(responseDataType.IsArray) {
// It's an array, what to do?
}
else {
// Not an array, what's next?
}

Mapping flat JSON/Dictionary to model (containing sub classes)

I want to turn a flat json string into a model, the destination class has subclasses, and the flat json has all of the sub class objects with prefix; like "{classname}.{property}".
{
"FirstName": "Joey",
"LastName": "Billy",
"EmploymentDetails.JobTitle": "JobTitle",
"EmploymentDetails.StartDate": "2015-01-01T00:00:00",
"ContactDetails.HouseNumberName": "10",
"ContactDetails.Road": "Road"
}
This is my destination class:
public class Person {
public string FirstName { get; set; }
public string LastName { get; set; }
public virtual EmploymentDetails EmploymentDetails { get;set;}
public virtual ContactDetails ContactDetails { get;set;}
}
public class EmploymentDetails {
public string JobTitle { get; set; }
public DateTime StartDate { get; set; }
}
public class ContactDetails {
public string HouseNumberName { get; set; }
public string Road { get; set; }
}
I tried the following:
public static void main() {
var json = #"{""FirstName"": ""Joey"",""LastName"": ""Billy"",""EmploymentDetails.JobTitle"": ""JobTitle"",""EmploymentDetails.StartDate"": ""2015-01-01T00:00:00"",""ContactDetails.HouseNumberName"": ""10"",""ContactDetails.Road"": ""Road"",}";
//try using AutoMapper
Mapper.CreateMap<string,Person>();
var personModel = Mapper.Map<Person>(json);
//just returns null values
//try using Newtonsoft
personModel = Newtonsoft.Json.JsonConvert.DeserializeObject<Person>(json);
//fills values but obviously returns no nested data
}
I know that Automapper has RecognizePrefix and RecognizeDestinationPrefix, but AutoMapper seems to only care if it's in the orignal object, and not a sub class.
Potentially I could take my JSON string and make it a Dictionary, but even then I don't know how to map it to a model with sub classes.
There was hope that I could have an infinite amount of sub classes and the JSON string could just map the flat JSON model to a model.
You can make a JsonConverter that does this in a generic way, using a ContractResolver to group and populate properties in the class being deserialized or its contained classes as appropriate.
You didn't ask for serialization, only deserialization, so that's what this does:
public class JsonFlatteningConverter : JsonConverter
{
readonly IContractResolver resolver;
public JsonFlatteningConverter(IContractResolver resolver)
{
if (resolver == null)
throw new ArgumentNullException();
this.resolver = resolver;
}
public override bool CanConvert(Type objectType)
{
return resolver.ResolveContract(objectType) is JsonObjectContract;
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.Null)
return null;
JObject jObject = JObject.Load(reader);
var contract = (JsonObjectContract)resolver.ResolveContract(objectType); // Throw an InvalidCastException if this object does not map to a JObject.
existingValue = existingValue ?? contract.DefaultCreator();
if (jObject.Count == 0)
return existingValue;
var groups = jObject.Properties().GroupBy(p => p.Name.Contains('.') ? p.Name.Split('.').FirstOrDefault() : null).ToArray();
foreach (var group in groups)
{
if (string.IsNullOrEmpty(group.Key))
{
var subObj = new JObject(group);
using (var subReader = subObj.CreateReader())
serializer.Populate(subReader, existingValue);
}
else
{
var jsonProperty = contract.Properties[group.Key];
if (jsonProperty == null || !jsonProperty.Writable)
continue;
if (jsonProperty != null)
{
var subObj = new JObject(group.Select(p => new JProperty(p.Name.Substring(group.Key.Length + 1), p.Value)));
using (var subReader = subObj.CreateReader())
{
var propertyValue = serializer.Deserialize(subReader, jsonProperty.PropertyType);
jsonProperty.ValueProvider.SetValue(existingValue, propertyValue);
}
}
}
}
return existingValue;
}
public override bool CanWrite { get { return false; } }
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
And then use it thusly:
var resolver = new DefaultContractResolver();
var settings = new JsonSerializerSettings { ContractResolver = resolver, Converters = new JsonConverter[] { new JsonFlatteningConverter(resolver) } };
var person = JsonConvert.DeserializeObject<Person>(json, settings);
Prototype fiddle.

Categories

Resources