Json.NET无法将索引属性反序列化为数组

时间:2015-11-08 15:16:06

标签: c# json json.net json-deserialization

这是一个延伸,但它是一个真实世界的例子,但却是蓬勃发展的。我们在列表中有一个包含多个Fluff对象的数据节点。它们根据列表中的索引命名,如:{ Fluff_0, Fluff_1, ..., Fluff_n }

当我反序列化这个对象时,我希望它被反序列化为List<Fluff>

有没有办法用JsonPropertyAttributes来装饰它,这样我就可以在Data对象中获得Fluff对象的有序通用List(或其他集合)?

[TestFixture]
public class FluffDeserializationTests
{
    [Test]
    public void FluffDeserialization()
    {
        var json = "{\"Data\": { \"Fluff_0\": {\"ID\": \"abc\"}, \"Fluff_1\": { \"ID\": \"abd\" } } }";
        var result = JsonConvert.DeserializeObject<Fluff>(json);
        Assert.That(result.Data.Things != null);
        Assert.That(result.Data.Things.Count, Is.EqualTo(2));
        Assert.That(result.Data.Things[0].ID, Is.EqualTo("abc"));
        Assert.That(result.Data.Things[1].ID, Is.EqualTo("abd"));
    }


    public class Fluff
    {
        public Data Data { get; set; }
    }

    public class Data
    {
        public List<Thing> Things { get; set; }
    }

    public class Thing
    {
        public string ID { get; set; }
    }
}

2 个答案:

答案 0 :(得分:4)

Json.Net中没有一个属性会直接将您的蓬松对象转换为列表,但是您可以自定义JsonConverter进行操作而不会有太多麻烦,然后装饰您的Data具有属性的类,告诉Json.Net使用转换器。

以下是转换器的外观。请注意,如果Fluff_n键序列中出现任何间隙,则此代码仍将在结果列表中保持其相对顺序,但不会保留间隙。我猜这不会成为一个问题,但只是我们。

class FluffDataConverter : JsonConverter
{
    readonly int PrefixLength = "Fluff_".Length;

    public override bool CanConvert(Type objectType)
    {
        return (objectType == typeof(Data));
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        JObject jo = JObject.Load(reader);
        List<Thing> things = jo.Properties()
                               .OrderBy(p => int.Parse(p.Name.Substring(PrefixLength)))
                               .Select(p => p.Value.ToObject<Thing>())
                               .ToList();
        return new Data { Things = things };
    }

    public override bool CanWrite
    {
        get { return false; }
    }

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

要使用此转换器,只需在[JsonConverter]类上添加Data属性,如下所示:

[JsonConverter(typeof(FluffDataConverter))]
public class Data
{
    public List<Thing> Things { get; set; }
}

当您重新运行测试代码时,它应该按照您的描述工作。

答案 1 :(得分:0)

你可以试试这个。

var things = new List<Thing>();
var json = "{\"Data\": { \"Fluff_0\": {\"ID\": \"abc\"}, \"Fluff_1\": { \"ID\": \"abd\" } } }";
JObject jObject = JObject.Parse(json);
var data = (JObject)jObject["Data"];  
var prop = data.Properties().Where(p => p.Name.Contains("Fluff")).Count();
if (prop > 0)
  for (int i = 0; i < prop; i++)
    things.Add(new Thing { ID = (string)((JObject)data["Fluff_" + i])["ID"]});  //please check if get null value