.net 使用string或int内容反序列化json属性

ruyhziif  于 2022-11-19  发布在  .NET
关注(0)|答案(2)|浏览(127)

我正在尝试使用.net内置函数反序列化对象。
让我们看看我尝试反序列化的数组“attributes”:

"attributes": [
{
    "trait_type": "Subseries",
    "value": "Templar Order"
},
{
    "trait_type": "Colorfulness",
    "value": 2,
    "min_value": 1,
    "max_value": 5
},
{
    "trait_type": "Style",
    "value": "CGI"
},
{
    "trait_type": "Material",
    "value": "Steel"
},
{
    "trait_type": "Special Effects",
    "value": "Rare"
},
{
    "trait_type": "Background",
    "value": "Rare"
}],

正如您所看到的,属性总是具有trait_type和值。
值可以是string或int类型。
最小值和最大值是可选,且总是int类型。
我正在纠结的是字段“value”。我试图从它创建一个类,但JSON反序列化器不会只将int转换为字符串(我会很好)

public class MetadataAttribute
{
    public MetadataAttribute(string Trait_Type, string Value)
    {
        trait_type = Trait_Type;
        value = Value;
    }
    public MetadataAttribute(string Trait_Type, int Value, int? Min_Value = null, int? Max_Value = null)
    {
        trait_type = Trait_Type;
        value = Value.ToString();
        min_value = Min_Value;
        max_value = Max_Value;
    }
    public MetadataAttribute() { }
    /// <summary>
    ///  the attribute name, eg sharpness
    /// </summary>
    public string trait_type { get; set; }
    /// <summary>
    /// the value of the attribute, eg 10
    /// </summary>
    public string value { get; set; }
    /// <summary>
    /// optional: the minimum value atribute to provide a possible range
    /// </summary>
    public int? min_value{get;set;}
    /// <summary>
    /// optional: the maximum value attribute to provide a possible range
    /// </summary>
    public int? max_value { get; set; }
}

当前反序列化器函数(当值中没有int时有效)

public static Metadata Load(string path)
{
    FileInfo testFile = new FileInfo(path);
    string text = File.ReadAllText(testFile.FullName);
    Metadata json = JsonSerializer.Deserialize<Metadata>(text);
    return json;
}

我该如何解决这种模糊性?

vfh0ocws

vfh0ocws1#

如果您可以定义两个数据模型,例如:

abstract class TraitInfo
{
    [JsonProperty("trait_type")]
    public string TraitType { get; set; }
    [JsonProperty("value")]
    public virtual object Value { get; set; }
}

class TraitString : TraitInfo
{
    public virtual string Value { get; set; }
}

class TraitNumber: TraitInfo
{
    public virtual int Value { get; set; }
    [JsonProperty("min_value")]
    public int MinValue { get; set; }
    [JsonProperty("max_value")]
    public int MaxValue { get; set; }
}

class Root
{
    [JsonProperty("attributes")]
    public List<TraitInfo> Traits { get; set; }
}

那么您可以为TraitInfo创建一个JsonConverter

class TraitInfoConverter : JsonConverter<TraitInfo>
{
    public override TraitInfo? ReadJson(JsonReader reader, Type objectType, TraitInfo? existingValue, bool hasExistingValue, JsonSerializer serializer)
    {
        var semiParsed = JObject.Load(reader);
        var value = semiParsed["value"];
        return value.Type switch
        {
            JTokenType.String => semiParsed.ToObject<TraitString>(),
            JTokenType.Integer => semiParsed.ToObject<TraitNumber>(),
            _ => throw new NotSupportedException()
        };
    }

    public override void WriteJson(JsonWriter writer, TraitInfo? value, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}

并且在反序列化期间,您可以指定此转换器

var result = JsonConvert.DeserializeObject<Root>(json, new JsonSerializerSettings { Converters = { new TraitInfoConverter() } });

请注意,如果在TraitInfo上使用JsonConverterAttribute,则ReadJson将处于无限循环中。
DotnetFiddle link

ego6inou

ego6inou2#

最好使用Newtonsoft.Json,但您可以更改该类以避免使用自定义序列化程序

public class MetadataAttribute
{
    //.... your code

        
    [System.Text.Json.Serialization.JsonPropertyName("value")]
    public object _value
    {
        get
        {
            if (int.TryParse(value, out var intValue)) return intValue;
            return this.value;
        }
        set { this.value = value.ToString(); }
    }
        
    /// <summary>
    /// the value of the attribute, eg 10
    /// </summary>
    [System.Text.Json.Serialization.JsonIgnore]
    public string value { get; set; }
    
    // ...your code
}

相关问题