using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Collections.ObjectModel;
using System.Runtime.Serialization;
using System.ComponentModel;
using System.Globalization;
using System.Collections.Specialized;
using System.Text.RegularExpressions;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Serialization;
public abstract class ServicePropertyBase
public abstract object GetValue();
public class ServiceProperty<T> : ServicePropertyBase
public ServiceProperty() { }
public ServiceProperty(T value) { this.Value = value; }
public T Value { get; set; }
public override object GetValue()
public class ServicePropertyConverter : JsonConverter
public override bool CanConvert(Type objectType)
return objectType.GetServicePropertyValueType() != null;
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
var valueType = objectType.GetServicePropertyValueType();
var value = serializer.Deserialize(reader, valueType);
return Activator.CreateInstance(objectType, value);
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
var baseValue = (ServicePropertyBase)value;
serializer.Serialize(writer, baseValue.GetValue());
internal static class ServicePropertyExtensions
public static Type GetServicePropertyValueType(this Type objectType)
if (objectType.IsGenericType && objectType.GetGenericTypeDefinition() == typeof(ServiceProperty<>))
return objectType.GetGenericArguments()[0];
public class ServicePropertyContractResolver : DefaultContractResolver
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
var property = base.CreateProperty(member, memberSerialization);
if (property.DefaultValueHandling == null && property.PropertyType.GetServicePropertyValueType() != null)
property.DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate;
public ServiceProperty<string> StringValue { get; set; }
public ServiceProperty<int> IntValue { get; set; }
public ServiceProperty<int?> NullableValue { get; set; }
public ServiceProperty<RootObject> RootObjectValue { get; set; }
public static void Test()
StringValue = new ServiceProperty<string>(),
IntValue = new ServiceProperty<int>(),
NullableValue = new ServiceProperty<int?>(),
RootObjectValue = new ServiceProperty<RootObject>(),
StringValue = new ServiceProperty<string>("hello"),
IntValue = new ServiceProperty<int>(121),
NullableValue = new ServiceProperty<int?>(232),
RootObjectValue = new ServiceProperty<RootObject>(new RootObject()),
static void Test(RootObject model)
var settings1 = new JsonSerializerSettings
Converters = { new ServicePropertyConverter() },
Formatting = Formatting.Indented,
DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate,
var settings2 = new JsonSerializerSettings
Converters = { new ServicePropertyConverter() },
Formatting = Formatting.Indented,
ContractResolver = new ServicePropertyContractResolver(),
static void Test(RootObject model, JsonSerializerSettings settings)
var json = JsonConvert.SerializeObject(model, settings);
Console.WriteLine("Serialized JSON for {0}", model);
var model2 = JsonConvert.DeserializeObject<RootObject>(json, settings);
var json2 = JsonConvert.SerializeObject(model2, settings);
Console.WriteLine("Deserialied and re-serialized JSON for {0}", model2);
Console.WriteLine(json2);
Assert.IsTrue(json == json2);
public static class Assert
public static void IsTrue(bool value)
throw new AssertionFailedException("failed");
public class AssertionFailedException : System.Exception
public AssertionFailedException() : base() { }
public AssertionFailedException(string s) : base(s) { }
public static void Main()
Console.WriteLine("Environment version: " + Environment.Version);
Console.WriteLine("Json.NET version: " + typeof(JsonSerializer).Assembly.FullName);