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

Custom JsonConverter - revert to default implemetation for array properties

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

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

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

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

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

我该怎么做?

当reader定位到一个值时,可以调用JsonSerializer.Deserialize(), JToken.Load(), JArray.Load() or JObject.Load()反序列化或加载该值。通常我更喜欢这样做而不是手动读取 "atomic",因为它确保正确处理嵌套并使 reader 正确定位到 JSON 流中的下一个项目。当位于 属性 值上时,使用适当的类型调用 JsonSerializer.Deserialize 将为您提供该 属性.

的默认反序列化实现

其实简单的写一个ReadJson method is to load the entire contents of the object into a 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;
            }
        }

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

        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;
                    }
                }
            }
        }