using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.ComponentModel;
using System.Xml.Serialization;
using System.Runtime.Serialization;
using System.Text.RegularExpressions;
using System.Globalization;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Serialization;
public Parent() { this.Props = new List<string>(); }
public int ParentId { get; set; }
public string Value { get; set; }
public List<string> Props { get; set; }
void OnSerializing(StreamingContext ctx)
VariablePropertyListExtensions.OnSerializing(Props, ref extensionData, false);
void OnSerialized(StreamingContext ctx)
VariablePropertyListExtensions.OnSerialized(Props, ref extensionData, false);
void OnDeserializing(StreamingContext ctx)
VariablePropertyListExtensions.OnDeserializing(Props, ref extensionData, false);
void OnDeserialized(StreamingContext ctx)
Props = new List<string>();
VariablePropertyListExtensions.OnDeserialized(Props, ref extensionData, false);
public class ListSurrogateDictionary<TListValue, TKey, TValue> : IDictionary<TKey, TValue>
readonly IList<IListValue> list;
readonly Func<int, TKey> toKey;
readonly Func<TKey, int> fromKey;
readonly Func<TListValue, TValue> ToValue;
readonly Func<TValue, TListValue> fromValue;
public ListSurrogateDictionary
public static class VariablePropertyListExtensions
public const string Prefix = "prop_";
readonly static Regex regex;
static VariablePropertyListExtensions()
regex = new Regex("^" + Prefix + @"\d+" + "$", RegexOptions.CultureInvariant | RegexOptions.Compiled);
public static void OnSerializing<TDictionary>(IList<string> props, ref TDictionary extensionData, bool keepUnknownProperties) where TDictionary : class, IDictionary<string, JToken>, new()
Debug.Assert(keepUnknownProperties || (extensionData == null || extensionData.Count == 0));
if (props == null || props.Count < 1)
extensionData = extensionData ?? new TDictionary();
for (int i = 0; i < props.Count; i++)
extensionData.Add(Prefix + (i + 1).ToString(NumberFormatInfo.InvariantInfo), (JValue)props[i]);
internal static void OnSerialized<TDictionary>(IList<string> props, ref TDictionary extensionData, bool keepUnknownProperties) where TDictionary : class, IDictionary<string, JToken>, new()
if (extensionData == null)
foreach (var name in extensionData.Keys.Where(k => regex.IsMatch(k)).ToList())
extensionData.Remove(name);
if (!keepUnknownProperties || extensionData.Count == 0)
internal static void OnDeserializing<TDictionary>(IList<string> props, ref TDictionary extensionData, bool keepUnknownProperties) where TDictionary : class, IDictionary<string, JToken>, new()
Debug.Assert(keepUnknownProperties || (extensionData == null || extensionData.Count == 0));
internal static void OnDeserialized<TDictionary>(IList<string> props, ref TDictionary extensionData, bool keepUnknownProperties) where TDictionary : class, IDictionary<string, JToken>, new()
if (extensionData == null)
foreach (var item in extensionData.Where(i => regex.IsMatch(i.Key)).ToList())
props.Add(item.Value.ToObject<string>());
extensionData.Remove(item.Key);
if (!keepUnknownProperties || extensionData.Count == 0)
public Parent parent { get; set; }
var json = @"{ ""parent"": {
internal static void Test()
var root = JsonConvert.DeserializeObject<RootObject>(json);
var json2 = JsonConvert.SerializeObject(root, Formatting.Indented);
Console.WriteLine("Re-serialized JSON: ");
Console.WriteLine(json2);
if (!JToken.DeepEquals(JToken.Parse(json), JToken.Parse(json2)))
throw new InvalidOperationException("!JToken.DeepEquals(JToken.Parse(json), JToken.Parse(json2))");
Console.WriteLine("Original and re-serialized JSON are equivalent.");
var root2 = new RootObject();
JsonConvert.PopulateObject(json, root2);
JsonConvert.PopulateObject(json, root2);
var json3 = JsonConvert.SerializeObject(root2);
if (!JToken.DeepEquals(JToken.Parse(json), JToken.Parse(json3)))
throw new InvalidOperationException("!JToken.DeepEquals(JToken.Parse(json), JToken.Parse(json3))");
Console.WriteLine("Original and re-populated JSON are equivalent.");
public static void Main()
Console.WriteLine("Json.NET version: " + typeof(JsonSerializer).Assembly.FullName);