这是一个延伸,但它是一个真实世界的例子,但却是蓬勃发展的。我们在列表中有一个包含多个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; }
}
}
答案 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