Json.net循环引用异常,即使使用JsonSerializerSettings

时间:2018-03-22 08:55:46

标签: c# json.net

我正在尝试序列化我的产品对象,但我的程序一直在崩溃。这可能是由于我的ProductPropertyValue和PropertyValue循环引用。但是你可以从我的JSON中看到,我的JSON中实际上没有循环引用,只有可能存在一个。

当然我在发布问题之前试图找到解决方案。我发现的大多数答案都包含了这些JsonSerializerSettings的一些变体:ReferenceLoopHandlingPreserveReferencesHandling。但无论我尝试设置什么设置,都没有效果。

我是否遗漏了一些明显的东西,或者我正在尝试做什么更好的解决方案?

JSON

{
    "id": "skdlfkioajzze",
    "properties": [{
        "id": "skdlfkioajzzf",
        "name": "Population",
        "value": 1000
    }, {
        "id": "skdlfkioajzzg",
        "name": "Weight",
        "value": 72.41
    }, {
        "id": "skdlfkioajzzh",
        "name": "Appendages",
        "values": [{
            "id": "skdlfkioajzzi",
            "name": "Legs",
            "value": 2
        }, {
            "id": "skdlfkioajzzj",
            "name": "Heads",
            "value": 1
        }]
    }, {
        "id": "skdlfkioajzzk",
        "name": "Species",
        "value": "Human"
    }]
}

序列化代码

string json;
try
{
    Product product = JsonConvert.DeserializeObject<Product>(json);
    var reserializedJson = JsonConvert.SerializeObject(product, new JsonSerializerSettings
    {
        ReferenceLoopHandling = ReferenceLoopHandling.Serialize,
        PreserveReferencesHandling = PreserveReferencesHandling.Objects
    });
    Product redeserializedJson = JsonConvert.DeserializeObject<Product>(reserializedJson);
    Debug.Log(reserializedJson);
}
catch (Exception e)
{
    Debug.Log(e.Message);
}

产品型号

public class Product
{
    public string Id { get; set; }
    public List<ProductPropertyValue> Properties { get; set; }
}

ProductPropertyValue类

public class ProductPropertyValue
{
    [JsonProperty("id")]
    public string PropertyId { get; set; }

    [JsonProperty("value")]
    public PropertyValue ValueObject { get; set; 
}

PropertyValue模型

[JsonConverter(typeof(PropertyValueConverter))]
public class PropertyValue
{
    public string StringValue { get; set; }
    public int IntValue { get; set; }
    public float FloatValue { get; set; }
    public List<ProductPropertyValue> ListValue { get; set; }

    public PropertyValue()
    {
        IntValue = int.MaxValue;
        FloatValue = float.MaxValue;
    }

    [JsonIgnore]
    public string Value
    {
        get
        {
            if (IntValue != int.MaxValue)
            {
                return IntValue.ToString();
            }

            if (FloatValue != float.MaxValue)
            {
                return FloatValue.ToString();
            }

            return StringValue;
        }
    }
}

PropertyValueConverter模型

public class PropertyValueConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return (objectType == typeof(PropertyValue));
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        JToken jObject = JToken.Load(reader);
        PropertyValue propertyValue = new PropertyValue();
        switch (reader.TokenType)
        {
            case JsonToken.Float:
                propertyValue.FloatValue = jObject.ToObject<float>();
                break;
            case JsonToken.Integer:
                propertyValue.IntValue = jObject.ToObject<int>();
                break;
            case JsonToken.String:
                propertyValue.StringValue = jObject.ToObject<string>();
                break;
            case JsonToken.EndArray:
            case JsonToken.StartArray:
                propertyValue.ListValue = new List<ProductPropertyValue>();
                List<JToken> tokens = jObject.ToList();
                foreach (JToken token in tokens)
                {
                    ProductPropertyValue prop = token.ToObject<ProductPropertyValue>();
                    if (prop != null)
                    {
                        propertyValue.ListValue.Add(prop);
                    }
                }
                break;
        }

        return propertyValue;
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        try
        {
            serializer.Serialize(writer, value);
        }
        catch (JsonWriterException)
        {
            Debug.Log("caught json writer exception");
        }
        catch (Exception e)
        {
            Debug.Log("caught exception " + e.Message);
        }

    }
}

1 个答案:

答案 0 :(得分:1)

好的,我解决了崩溃问题!问题是我的自定义JsonConverter一直在无限循环中调用自己。我必须将[JsonConverter(typeof(PropertyValueConverter))]注释从PropertyValue模型移动到ProductPropertyValue模型。

这就是我现在的代码:

ProductPropertyValue类

public class ProductPropertyValue
{
    [JsonProperty("id")]
    public string PropertyId { get; set; }

    [JsonProperty("value")]
    [JsonConverter(typeof(PropertyValueConverter))]
    public PropertyValue ValueObject { get; set; 
}

PropertyValue模型

public class PropertyValue
{
    public string StringValue { get; set; }
    public int IntValue { get; set; }
    public float FloatValue { get; set; }
    public List<ProductPropertyValue> ListValue { get; set; }

    public PropertyValue()
    {
        IntValue = int.MaxValue;
        FloatValue = float.MaxValue;
    }

    [JsonIgnore]
    public string Value
    {
        get
        {
            if (IntValue != int.MaxValue)
            {
                return IntValue.ToString();
            }

            if (FloatValue != float.MaxValue)
            {
                return FloatValue.ToString();
            }

            return StringValue;
        }
    }
}