自定义JsonConverter - 恢复为数组属性的默认实现

时间:2015-04-14 11:14:13

标签: c# json json.net

我有一个自定义JsonConverter,我需要更改某些属性的默认序列化和反序列化。看看反序列化:

我正在覆盖ReadJson方法,如下所示:

while (reader.Read())
{
    if (reader.TokenType == JsonToken.PropertyName)
    {
        var propertyName = reader.Value.ToString();

        if (reader.Read())
        {
            ...

然后我可以检查TokenType,如果合适,可以自定义工作。这适用于大多数类型,但如果我有一个Enumerable属性并已被序列化为JsonArray,那么我想在继续我的自定义东西之前使用该属性的默认实现。

我该怎么做?

1 个答案:

答案 0 :(得分:1)

当读者找到某个值时,您可以拨打JsonSerializer.Deserialize()JToken.Load()JArray.Load()JObject.Load()来反序列化或加载该值。通常我更喜欢这样做来进行手动“原子”读取,因为它确保正确处理嵌套并使读者正确定位JSON流中的下一个项目。当定位在属性值上时,使用适当的类型调用JsonSerializer.Deserialize将为您提供该属性的反序列化的默认实现。

实际上,编写ReadJson方法的一种简单方法是将对象的全部内容加载到JObject中,然后遍历属性:

        var obj = JObject.Load(reader);
        foreach (var property in obj.Properties())
        {
            switch (property.Name)
            {
                case "Data2":
                    {
                        // For example
                        myClass.Data2 = obj.ToObject<List<double>>(serializer);
                    }
                    break;
                    // More cases as necessary
                default:
                    Debug.WriteLine("Unknown property " + property);
                    break;
            }
        }

如果出于某种原因你不想这样做,你可以阅读逐个属性并反序列化或加载单个值:

        while (reader.Read() && reader.TokenType != JsonToken.EndObject)
        {
            if (reader.TokenType == JsonToken.PropertyName)
            {
                var propertyName = reader.Value.ToString();

                if (reader.Read())
                {
                    switch (propertyName)
                    {
                        case "Data1":
                            {
                                // Expecting a double value.
                                if (reader.TokenType == JsonToken.Integer || reader.TokenType == JsonToken.Float)
                                    myClass.Data1 = Convert.ToDouble(reader.Value);
                                else
                                {
                                    // Unknown value, skip or throw an exception
                                    JToken.Load(reader);
                                }
                            }
                            break;
                        case "Data2":
                            {
                                // For example
                                myClass.Data2 = serializer.Deserialize<List<double>>(reader);
                            }
                            break;
                        case "Data3":
                            {
                                // Expecting a string value.
                                myClass.Data3 = JToken.Load(reader).ToString();
                            }
                            break;
                        default:
                            {
                                // Unknown property, skip or throw an exception
                                var unknownValue = JToken.Load(reader);
                                Debug.WriteLine(string.Format("Uknown property \"{0}\" with value: {1}", propertyName, unknownValue));
                            }
                            break;
                    }
                }
            }
        }