Json.net反序列化不一致的JSON

4

我正在处理一个不一致的Json数据,想要将其反序列化为我的.Net类。问题是有时我有一个对象,有时它是一个数组。如何最好地解决这个问题?使用转换器?以下是我的Json数据片段:

[
{
"@class": "odd",
"td": [
  {
    "@class": "user",
    "@onmouseover": "userInfo('469');",
    "@onmouseout": "userInfo(0);",
    "@onmousemove": "moveSlotInfo();",
    "#text": " AAA"
  },
  {
    "@id": "day-469-2014-04-07",
    "@style": "vertical-align: top;",
    "table": {
      "@class": "ss",
      "@cellspacing": "1",
      "tbody": {
        "tr": {
          "td": {
            "@class": "as",
            "@style": "color: #ffffff; background-color: #4040ff;",
            "@onmouseover": "this.className=(document.week_vs_doctor.activityId.value==-1?'sd':'sp');slotInfo('177935',false);",
            "@onmouseout": "this.className='as';slotInfo(0,false);",
            "@onmousemove": "moveSlotInfo();",
            "#text": "KAVAul"
          }
        }
      }
    }
  }
]
},
{
"@class": "even",
"td": [
  {
    "@class": "user",
    "@onmouseover": "userInfo('262');",
    "@onmouseout": "userInfo(0);",
    "@onmousemove": "moveSlotInfo();",
    "#text": " BBB"
  },
  {
    "@id": "day-262-2014-04-07",
    "@style": "vertical-align: top;",
    "table": {
      "@class": "ss",
      "@cellspacing": "1",
      "tbody": {
        "tr": [
          {
            "td": {
              "@class": "as",
              "@style": "color: #ffffff; background-color: #4040ff;",
              "@onmouseover": "this.className=(document.week_vs_doctor.activityId.value==-1?'sd':'sp');slotInfo('174318',false);",
              "@onmouseout": "this.className='as';slotInfo(0,false);",
              "@onmousemove": "moveSlotInfo();",
              "#text": "KAVA "
            }
          },
          {
            "td": {
              "@class": "as",
              "@style": "color: #000000; background-color: #ffc0c0;",
              "@onmouseover": "this.className=(document.week_vs_doctor.activityId.value==-1?'sd':'sp');slotInfo('174338',false);",
              "@onmouseout": "this.className='as';slotInfo(0,false);",
              "@onmousemove": "moveSlotInfo();",
              "#text": "Dagbak"
            }
          }
        ]
      }
    }
  }
]
}
]

问题出在 tr 对象上,它可能是对象(Object)或数组(Array)。
下面是我的代码片段:
    public class Td2
{
    [JsonProperty("@class")]
    public string TdClass { get; set; }

    [JsonProperty("@style")]
    public string style { get; set; }

    [JsonProperty("@onmouseover")]
    public string onmouseover { get; set; }

    [JsonProperty("@onmouseout")]
    public string onmouseout { get; set; }

    [JsonProperty("@onmousemove")]
    public string onmousemove { get; set; }

    [JsonProperty("#text")]
    public string text { get; set; }
}

public class Tr2
{
    public Td2 td { get; set; }
}

public class Tbody2
{
    [JsonProperty]
    [JsonConverter(typeof(ScheduleJsonConverter<Tr2>))]
    public List<Tr2> tr { get; set; }
}

public class Table
{
    [JsonProperty("@cellspacing")]
    public string cellspacing { get; set; }

    public Tbody2 tbody { get; set; }

    [JsonProperty("@class")]
    public string tClass { get; set; }
}

包括一个相关的代码片段(和/或突出显示)“不一致性”。不要让它变得困难。 - user2864740
我猜这个人在处理 Tr 元素时遇到了问题。在 JSON 中,它显示为单个对象。然而,一个表可以有多行。 - kmacdonald
如果您查看Json片段和下面的文本“问题出在tr对象上,它可能是对象或数组。”,您会发现这并不难 ;) - DreamNet
1个回答

4
我从某个地方得到了这个转换器,它在我的一个项目中使用。我很想给出信用。我会尝试搜索这篇文章。然而,这应该可以解决你的问题。
编辑:啊哈,找到了:JSON.NET 反序列化对象数组中的对象 将此属性添加到可能是单个对象或对象数组的类中,如下所示:
public class Tbody2
{
     [JsonProperty]
     [JsonConverter(typeof (ObjectToArrayConverter<Tr2>))]
     public List<Tr2> tr { get; set; }
 }

如果JSON只有一个元素而不是数组,转换器将使用单个元素填充数组。否则,它将反序列化为列表。

public class ObjectToArrayConverter<T> : CustomCreationConverter<List<T>> where T : new()
{
    public override List<T> Create(Type objectType)
    {
        return new List<T>();
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        var target = new List<T>();

        try
        {
            // Load JObject from stream
            var jArray = JArray.Load(reader);

            // Populate the object properties
            serializer.Populate(jArray.CreateReader(), target);
        }
        catch (JsonReaderException)
        {
            // Handle case when object is not an array...

            // Load JObject from stream
            var jObject = JObject.Load(reader);

            // Create target object based on JObject
            var t = new T();

            // Populate the object properties
            serializer.Populate(jObject.CreateReader(), t);

            target.Add(t);
        }

        return target;
    }
}

2
谢谢兄弟,虽然我不得不更改你的代码,而不是使用会产生太多异常处理的Try和Catch,我使用了If和Else,并使用reader.TokenType。这样做速度快得多。如果你想,我可以发布我的代码,以便任何人都可以获得一些帮助 ;) - DreamNet
是的,好主意。我刚刚将另一篇帖子中的内容复制粘贴到我的项目中。我想我会这样做。 - kmacdonald
我知道有点晚了,但是祝福你和所有跟随你的人! - Wesley Long

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接