CSharp · Console
using System;
using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
public class Program
{
public static void Main()
{
string json = @"
[
{
""FirstName"": ""Jane"",
""LastName"": ""Doe"",
""Birthday"": ""1988-10-06T00:00:00""
},
{
""FirstName"": ""Joe"",
""LastName"": ""Schmoe"",
""Birthday"": null
}
]";
RootModelConverter converter = new RootModelConverter();
RootModel model = JsonConvert.DeserializeObject<RootModel>(json, converter);
model.Addresses.Add(new Address
{
Id = 1,
Street = "123 Main Street",
City = "Birmingham",
State = "AL",
PostalCode = "35201",
Country = "USA"
});
foreach (var person in model.People)
{
person.AddressId = 1;
}
json = JsonConvert.SerializeObject(model, Formatting.Indented);
Console.WriteLine(json);
Console.WriteLine();
model = JsonConvert.DeserializeObject<RootModel>(json, converter);
foreach (var person in model.People)
{
Address addr = model.Addresses.FirstOrDefault(a => a.Id == person.AddressId);
Console.Write(person.FirstName + " " + person.LastName);
Console.WriteLine(addr != null ? " lives in " + addr.City + ", " + addr.State : "");
}
}
}
public class RootModelConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return objectType == typeof(RootModel);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
JToken token = JToken.Load(reader);
RootModel model = new RootModel();
if (token.Type == JTokenType.Array)
{
// we have a Version 3 or earlier model, which was just a list of people.
model.People = token.ToObject<List<Person>>(serializer);
model.Addresses = new List<Address>();
return model;
}
else if (token.Type == JTokenType.Object)
{
// Check that the version is something we are expecting
string version = (string)token["Version"]; // case sensitive!
if (version == "4")
{
serializer.Populate(token.CreateReader(), model);
return model;
}
else
{
throw new JsonException("Unexpected version: " + version);
}
}
else
{
throw new JsonException("Unexpected token: " + token.Type);
}
}
public override bool CanWrite
{
get { return false; }
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
public class RootModel
{
public int Version { get { return 4; } }
public List<Person> People { get; set; }
public List<Address> Addresses { get; set; }
}
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
public DateTime? Birthday { get; set; }
public int AddressId { get; set; }
// This property is here to support transitioning from the Version 2 model to Version 3
[JsonProperty]
private string Name
{
set
{
if (value != null)
{
string[] parts = value.Split(' ');
if (parts.Length > 0) FirstName = parts[0];
if (parts.Length > 1) LastName = parts[1];
}
}
}
}
public class Address
{
public int Id { get; set; }
public string Street { get; set; }
public string City { get; set; }
public string State { get; set; }
public string PostalCode { get; set; }
public string Country { get; set; }
}