当值可以是数组或单个项时,C#DataContractJsonSerializer将失败

时间:2011-10-04 12:09:16

标签: c# arrays json datacontract serializer

我使用DataContractJsonSerializer将json字符串解析为对象hierarchie。 json字符串如下所示:

{
    "groups": [
        {
            "attributes": [
                {
                    "sortOrder": "1",
                    "value": "A"
                },
                {
                    "sortOrder": "2",
                    "value": "B"
                }
            ]
        },
        {
            "attributes": {
                "sortOrder": "1",
                "value": "C"
            }
        }
    ]
}

正如您所看到的,“属性”的子值可以是数组或单个项目。 我找到了问题发生的代码部分:

[DataContract]
public class ItemGroup
{
    [DataMember(Name="attributes")]
    public List<DetailItem> Items  { get; set; }
}

这适用于第一个但未通过第二个。

有人对此有答案吗?

THX

3 个答案:

答案 0 :(得分:3)

如果您控制JSON的创建方式,那么即使它只包含一个元素,也要确保属性是一个数组。然后第二个元素看起来像这样并解析得很好。

    {
        "attributes": [{
            "sortOrder": "1",
            "value": "C"
        }]
    }

答案 1 :(得分:3)

正如Daniel所说,如果你可以控制Json的创建,那么最好继续这样做。 但是,如果你不能,那么你可以使用Json.Net库&amp;来自的JsonObject类 this链接写一些代码,如:

JObject o = (JObject)JsonConvert.DeserializeObject(input);
dynamic json = new JsonObject(o);
foreach (var x in json.groups)
{
      var attrs = x.attributes;
      if (attrs is JArray)
      {
           foreach (var y in attrs)
           {
               Console.WriteLine(y.value);
           }
      }
      else
      {
          Console.WriteLine(attrs.value);
      }
 }

答案 2 :(得分:1)

我尝试使用DataContractJsonSerializer,JavaScriptSerializer和JSON.Net,并且没有人会在所有情况下成功直接反序列化到对象。我使用类似的方法作为L.B,使用JSON.Net,虽然没有使用动力学和额外的JsonObject类。使我的代码适应您的场景将如下所示:

private List<ItemGroup> ParseItemGroupList(string input)
    {
        JObject json = JObject.Parse(input);

        List<ItemGroup> groups = new List<ItemGroup>();
        JArray gArray = json["groups"] as JArray;
        foreach (var gToken in gArray)
        {
            ItemGroup newGroup = new ItemGroup();
            JToken attrToken = gToken["attributes"] as JToken;
            if (attrToken is JArray)
            {
                newGroup.Items = attrToken.Children().Select(MapDetailItem()).ToList();
            }
            else
            {
                newGroup.Items = new List<DetailItem>() { MapDetailItem().Invoke(attrToken) };
            }

            groups.Add(newGroup);
        }

        return groups;
    }

    private static Func<JToken, DetailItem> MapDetailItem()
    {
        return json => new DetailItem
        {
            SortOrder = (string)json["sortOrder"],
            Value = (string)json["value"]
        };
    }

希望有人会为JSON.Net添加一个设置,以允许它强制反序列化到具有单个项目的集合,而不是抛出异常。遗憾的是,当只有一小部分JSON无法自动解析时,您必须手动执行所有解析。