using System.Collections;
using System.Collections.Generic;
using System.Runtime.Serialization.Formatters;
using System.ComponentModel.DataAnnotations;
using System.Globalization;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Serialization;
[JsonConverter(typeof(FJson))]
public int id { get; set; }
public string name { get; set; }
[JsonConverter(typeof(BConverter))]
public string name { get; set; }
public static partial class JsonExtensions
public static JToken DefaultFromObject(this JsonSerializer serializer, object value)
return JValue.CreateNull();
var dto = Activator.CreateInstance(typeof(DefaultSerializationDTO<>).MakeGenericType(value.GetType()), value);
var root = JObject.FromObject(dto, serializer);
return root["Value"].RemoveFromLowestPossibleParent() ?? JValue.CreateNull();
public static object DefaultToObject(this JToken token, Type type, JsonSerializer serializer = null)
var oldParent = token.Parent;
var dtoToken = new JObject(new JProperty("Value", token));
var dtoType = typeof(DefaultSerializationDTO<>).MakeGenericType(type);
var dto = (IHasValue)(serializer ?? JsonSerializer.CreateDefault()).Deserialize(dtoToken.CreateReader(), dtoType);
token.RemoveFromLowestPossibleParent();
return dto == null ? null : dto.GetValue();
[JsonObject(NamingStrategyType = typeof(DefaultNamingStrategy), IsReference = false)]
class DefaultSerializationDTO<T> : IHasValue
public DefaultSerializationDTO(T value) { this.Value = value; }
public DefaultSerializationDTO() { }
[JsonConverter(typeof(NoConverter)), JsonProperty(ReferenceLoopHandling = ReferenceLoopHandling.Serialize)]
public T Value { get; set; }
object IHasValue.GetValue() { return Value; }
public static TJToken RemoveFromLowestPossibleParent<TJToken>(this TJToken node) where TJToken : JToken
var property = node.Parent as JProperty;
if (toRemove.Parent != null)
public class NoConverter : JsonConverter
public override bool CanConvert(Type objectType) { throw new NotImplementedException(); }
public override bool CanRead { get { return false; } }
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { throw new NotImplementedException(); }
public override bool CanWrite { get { return false; } }
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { throw new NotImplementedException(); }
public class FJson : JsonConverter
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
JToken t = serializer.DefaultFromObject(value);
if (t.Type != JTokenType.Object)
writer.WriteStartObject();
private void WriteJson(JsonWriter writer, JObject value)
foreach (var p in value.Properties())
WriteJson(writer, (JObject)p.Value);
public override object ReadJson(JsonReader reader, Type objectType,
object existingValue, JsonSerializer serializer)
throw new NotImplementedException();
public override bool CanConvert(Type objectType)
public sealed class BConverter : JsonConverter
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
var obj = (JObject)serializer.DefaultFromObject(value);
obj["BConverterCalled"] = true;
public override bool CanConvert(Type objectType)
throw new NotImplementedException();
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
throw new NotImplementedException();
public static void Test()
var settings = new JsonSerializerSettings
ContractResolver = new CamelCasePropertyNamesContractResolver()
var jsonFormatted = JsonConvert.SerializeObject(a, Formatting.Indented, settings);
Console.WriteLine(jsonFormatted);
var json = JsonConvert.SerializeObject(a, Formatting.None, settings);
Assert.IsTrue(json == "{\"id\":1,\"name\":null,\"name\":\"value\",\"BConverterCalled\":true}");
public static void Main()
Console.WriteLine("Environment version: " + Environment.Version);
Console.WriteLine("Json.NET version: " + typeof(JsonSerializer).Assembly.FullName);
Console.WriteLine("Failed with unhandled exception: ");