Search code examples
c#.netjson.netprimitive

Overriding Default Primitive Type Handling in Json.Net


Is there a way to override the default deserialization behaviour of Json.net when handling primitive types? For example when deserializing the json array [3.14,10,"test"] to a type of object[] 3.14 will be of type double and 10 will be of type long. Is there anyway I can intercept or override this type decision so I could deserialize the values as decimal and int respectively?

I basically always want json integers to always return as int and floats to return as decimal. This will save me some having to inject double to decimal conversions in my code.

I've looked into extending Newtonsoft.Json.Serialization.DefaultContractResolver and implementing my own Newtonsoft.Json.JsonConverter but I have not discovered any way to implement this desired override.

Example code to reproduce

object[] variousTypes = new object[] {3.14m, 10, "test"};
string jsonString = JsonConvert.SerializeObject(variousTypes);
object[] asObjectArray = JsonConvert.DeserializeObject<object[]>(jsonString); // Contains object {double}, object {long}, object {string}

Solution

  • I think, this should work

    public class MyReader : JsonTextReader
    {
        public MyReader(string s) : base(new StringReader(s))
        {
        }
    
        protected override void SetToken(JsonToken newToken, object value)
        {
            object retObj = value;
            if (retObj is long) retObj = Convert.ChangeType(retObj, typeof(int));
            if (retObj is double) retObj = Convert.ChangeType(retObj, typeof(decimal));
    
            base.SetToken(newToken, retObj);
        }
    }
    
    
    object[] variousTypes = new object[] { 3.14m, 10, "test" };
    string jsonString = JsonConvert.SerializeObject(variousTypes);
    
    JsonSerializer serializer = new JsonSerializer();
    var asObjectArray = serializer.Deserialize<object[]>(new MyReader(jsonString));