C# JSON deserialization: can I intercept the deserialization and optionally change the result?

守給你的承諾、 提交于 2019-12-12 08:47:36

问题


We've got some JSON that we are deserializing into a strongly-typed object graph in C#. However, we've got one issue: sometimes there is an "empty" value in the JSON (e.g., empty string) in a property that maps to a boolean value in our model.

In our case, we know that 100% of the time, we can translate these "blank" values to Boolean false.

However, the JSON deserializers I've tried don't know about this (understandably).

I've been trying to find a way to intercept the deserialization of each property, and optionally override the output. I.e., if there was an "interceptor" method I could register, that looked like this:

    public Boolean JsonDeserializationInterceptor(String rawJson, System.Type targetType, out object result)
    {
        Boolean overrodeValue = false;
        result = null;
        if(targetType == typeof(System.Boolean))
        {
            overrodeValue = true;
            // We'll pretend that we're interpreting the string "Yes" as
            // true, and all other values are false.
            if (rawJson != null && rawJson.ToLower() == "\"yes\"")
                result = true;
            else
                result = false;
        }

        return overrodeValue;
    }

That's just hypothetical, of course, but hopefully it gives you an idea of what I'm trying to accomplish.

In my research I have not been able to figure out a way to do this. I've looked at Json.NET, System.Runtime.Serialization.Json.DataContractJsonSerializer, and System.Web.Script.Serialization.JavaScriptSerializer. I bet there is a way to do this, and I just haven't been able to figure it out.

Edit: I think you might be able to use the JsonConverterAttribute, but so far I have not been able to get that working.


回答1:


Writing a custom JsonConverter for a primitive type is pretty straghtforward:

using System;
using Newtonsoft.Json;

namespace So16972364JsonDeserializeConverter
{
    class BoolConverter : JsonConverter
    {
        public override void WriteJson (JsonWriter writer, object value, JsonSerializer serializer)
        {
            serializer.Serialize(writer, value);
        }

        public override object ReadJson (JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            switch (reader.TokenType) {
                case JsonToken.String:
                    if ((string)reader.Value == "")
                        return false;
                    break;
                case JsonToken.Boolean:
                    return reader.Value;
            }
            throw new JsonReaderException("Expected boolean or empty string.");
        }

        public override bool CanConvert (Type objectType)
        {
            return objectType == typeof(bool);
        }
    }

    class Program
    {
        const string json = @"
{
    b1: true,
    b2: false,
    b3: ''
}
";

        static void Main ()
        {
            Foo foo = JsonConvert.DeserializeObject<Foo>(json, new JsonSerializerSettings {
                Converters = { new BoolConverter() }
            });
            Console.WriteLine(JsonConvert.SerializeObject(foo, Formatting.Indented));
            Console.ReadKey();
        }
    }

    class Foo
    {
        public bool b1, b2, b3;
    }
}

This code overrides deserialization of all boolean values. If you need this only for specific members, you need to apply JsonConverterAttribute.




回答2:


There is an error in the example above. Instead of

public override void WriteJson (JsonWriter writer, object value, JsonSerializer serializer)
{
    serializer.Serialize(writer, value);
}

there should be

public override void WriteJson (JsonWriter writer, object value, JsonSerializer serializer)
{
    writer.WriteValue(value);
}

otherwise you will get StackOverflow exception! Strangely why nobody hasn't written about it yet.



来源:https://stackoverflow.com/questions/16972364/c-sharp-json-deserialization-can-i-intercept-the-deserialization-and-optionally

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!