C#将Json转换为具有不同数据类型的重复属性名称的对象 [英] C# Convert Json to object with duplicated property name with different data type

查看:277
本文介绍了C#将Json转换为具有不同数据类型的重复属性名称的对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个json字符串,具有重复的属性名称和不同的数据类型.如果我删除所有重复的其他数据类型,它将正常工作.

i have a json string with duplicated property name with different data types. if i removed all duplicated other data types, it will work fine.

{
   "data":[
      {
         "ctr":0,
         "spend":11839.8600,
         "clicks":6402
      },
      {
         "ctr":0,
         "spend":12320.5000,
         "clicks":5789
      },
      {
         "clicks":{
            "value":13156.0,
            "prior_year":0.0,
            "prior_month":14122.0,
            "prior_month_perc":0.0684039087947882736156351792,
            "prior_year_perc":0.0
         }
      }
   ],
   "timing":null,
   "warnings":[

   ],
   "success":true
}

这是我的模型课

  public class MyTestModel
    {
        public int? ctr { get; set; }
        public decimal? spend { get; set; }
        public int? clicks { get; set; }
    }

如果我删除了这个被截断的json部分,程序将正常工作.

if i removed this snipped json part, program will work.

        {
         "clicks":{
            "value":13156.0,
            "prior_year":0.0,
            "prior_month":14122.0,
            "prior_month_perc":0.0684039087947882736156351792,
            "prior_year_perc":0.0
         }

有什么方法可以停止将不受支持的类型绑定到模型属性.

are there any method to stop binding unsupported types to model property.

推荐答案

您可以使用JsonConverter支持联合"类中的一种/两种类型.

You can use a JsonConverter to support either/both types in a 'union' class.

public partial class ClicksClass
{
    [JsonProperty("value")]
    public long Value { get; set; }

    [JsonProperty("prior_year")]
    public long PriorYear { get; set; }

    [JsonProperty("prior_month")]
    public long PriorMonth { get; set; }

    [JsonProperty("prior_month_perc")]
    public double PriorMonthPerc { get; set; }

    [JsonProperty("prior_year_perc")]
    public long PriorYearPerc { get; set; }
}

public partial struct ClicksUnion
{
    public ClicksClass ClicksClass;
    public long? Integer;

    public static implicit operator ClicksUnion(ClicksClass ClicksClass) => new ClicksUnion { ClicksClass = ClicksClass };
    public static implicit operator ClicksUnion(long Integer) => new ClicksUnion { Integer = Integer };
}

internal static class Converter
{
    public static readonly JsonSerializerSettings Settings = new JsonSerializerSettings
    {
        MetadataPropertyHandling = MetadataPropertyHandling.Ignore,
        DateParseHandling = DateParseHandling.None,
        Converters =
        {
            ClicksUnionConverter.Singleton,
            new IsoDateTimeConverter { DateTimeStyles = DateTimeStyles.AssumeUniversal }
        },
    };
}

internal class ClicksUnionConverter : JsonConverter
{
    public override bool CanConvert(Type t) => t == typeof(ClicksUnion) || t == typeof(ClicksUnion?);

    public override object ReadJson(JsonReader reader, Type t, object existingValue, JsonSerializer serializer)
    {
        switch (reader.TokenType)
        {
            case JsonToken.Integer:
                var integerValue = serializer.Deserialize<long>(reader);
                return new ClicksUnion { Integer = integerValue };
            case JsonToken.StartObject:
                var objectValue = serializer.Deserialize<ClicksClass>(reader);
                return new ClicksUnion { ClicksClass = objectValue };
        }
        throw new Exception("Cannot unmarshal type ClicksUnion");
    }

    public override void WriteJson(JsonWriter writer, object untypedValue, JsonSerializer serializer)
    {
        var value = (ClicksUnion)untypedValue;
        if (value.Integer != null)
        {
            serializer.Serialize(writer, value.Integer.Value);
            return;
        }
        if (value.ClicksClass != null)
        {
            serializer.Serialize(writer, value.ClicksClass);
            return;
        }
        throw new Exception("Cannot marshal type ClicksUnion");
    }

    public static readonly ClicksUnionConverter Singleton = new ClicksUnionConverter();
}

这意味着,一旦解析,只要进入ClickUnion实例,就可以检查哪个字段不为null,这就是您使用的字段.当然,这取决于您的用例.

This means that, once parsed, whenever you get to the ClickUnion instances, you can check which field is not null, and that is the one you use. It depends on your usecase of course.

顺便说一句,我用此网站从json

BTW, I used this web site to write the classes from the json

这篇关于C#将Json转换为具有不同数据类型的重复属性名称的对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆