C# 如何反序列化具有不同名称的对象数组?
在使用C#的Windows Phone应用程序中,我尝试使用以下结构反序列化一些JSON:C# 如何反序列化具有不同名称的对象数组?,c#,windows-phone,json.net,C#,Windows Phone,Json.net,在使用C#的Windows Phone应用程序中,我尝试使用以下结构反序列化一些JSON: [ { "kite" : { "supplier" : "ABC", "currency" : "GBP", "cost" : "7.98" } }, { "puzzle" : { "supplier" : "DEF", "currency" : "USD", "cost" : "7.98" } }, { "b
[ { "kite" : { "supplier" : "ABC",
"currency" : "GBP",
"cost" : "7.98"
} },
{ "puzzle" : { "supplier" : "DEF",
"currency" : "USD",
"cost" : "7.98"
} },
{ "ball" : { "supplier" : "DEF",
"currency" : "USD",
"cost" : "5.49"
} }
]
这是一份玩具清单,其中玩具(风筝、拼图、球)的名称事先不知道。我无法控制JSON的格式
使用json2csharp.com,我可以获得以下类:
public class Kite
{
public string supplier { get; set; }
public string currency { get; set; }
public string cost { get; set; }
}
public class Puzzle
...
public class Ball
...
public class RootObject
{
public Kite kite { get; set; }
public Puzzle puzzle { get; set; }
public Ball ball { get; set; }
}
在我看来,这就像是一个“玩具”对象数组,但我不知道在反序列化时应该采取什么方法
我工作过的唯一代码是基本代码:
var root = JsonConvert.DeserializeObject(rawJSON);
我认为下面的方法可能会奏效,但如果它奏效(而且不行),我会失去玩具的名称:
公共类玩具
{
公共字符串提供程序{get;set;}
公共字符串货币{get;set;}
公共字符串成本{get;set;}
}
List-toyList=(List)JsonConvert.DeserializeObject(rawJSON,typeof(List));
有什么建议吗?很接近了。如果您在问题中定义了
玩具
类,则可以反序列化到列表
。因此,每个玩具实际上都由一个字典
表示,其中只有一个条目。键
是玩具的名称,值
是玩具
信息。下面是一个演示:
string json = @"
[ { ""kite"" : { ""supplier"" : ""ABC"",
""currency"" : ""GBP"",
""cost"" : ""7.98""
} },
{ ""puzzle"" : { ""supplier"" : ""DEF"",
""currency"" : ""USD"",
""cost"" : ""7.98""
} },
{ ""ball"" : { ""supplier"" : ""DEF"",
""currency"" : ""USD"",
""cost"" : ""5.49""
} }
]";
List<Dictionary<string, Toy>> list =
JsonConvert.DeserializeObject<List<Dictionary<string, Toy>>>(json);
foreach (Dictionary<string, Toy> dict in list)
{
KeyValuePair<string, Toy> kvp = dict.First();
Console.WriteLine("toy: " + kvp.Key);
Console.WriteLine("supplier: " + kvp.Value.Supplier);
Console.WriteLine("cost: " + kvp.Value.Cost + " (" + kvp.Value.Currency + ")");
Console.WriteLine();
}
诚然,这个解决方案有点“笨重”,因为最好将玩具的名称包含在toy
类本身中,而不是有一个插入的字典来绊倒。有两种方法可以解决这个问题。一种方法是在Toy
类上添加Name
属性,将其反序列化到如上所示的相同结构中,然后进行一点后处理,将名称从每个字典
移动到相应的Toy
,在此过程中构建一个新的列表
。第二种方法是创建一个自定义的JsonConverter
,在反序列化过程中处理此转换。如果您愿意,我很乐意演示这两种备选方法中的任何一种。请告诉我。如果您只需要快速和肮脏,那么上述方法应该可以
使用自定义JsonConverter的替代方法
这种方法有点“干净”,因为我们可以将所有的玩具
信息放在一个强类型对象上,并将所有反序列化逻辑分开,这样就不会弄乱主代码
首先,我们需要更改您的玩具
类,为其指定名称
属性
class Toy
{
public string Name { get; set; }
public string Supplier { get; set; }
public string Currency { get; set; }
public decimal Cost { get; set; }
}
接下来,我们创建一个继承自的类
您会注意到,这与上一个示例给出的输出完全相同,但代码更简洁。它看起来就像是一本字典。风筝、拼图和球是关键。如果对象具有供应商、货币和成本属性,则值将是某种类型。不过,我目前无法研究如何反序列化。不过,我会考虑使用某种动态对象,也许会将其转化为更具体的东西。布赖恩,我要到稍后才会对你的建议进行测试,但它看起来很棒!我很想知道你会如何使用定制的JsonConverter,因为这不是我所熟悉的。当然。我已经用这种替代方法更新了我的答案。
toy: kite
supplier: ABC
cost: 7.98 (GBP)
toy: puzzle
supplier: DEF
cost: 7.98 (USD)
toy: ball
supplier: DEF
cost: 5.49 (USD)
class Toy
{
public string Name { get; set; }
public string Supplier { get; set; }
public string Currency { get; set; }
public decimal Cost { get; set; }
}
class ToyConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
// This lets JSON.Net know that this converter can handle Toy objects
return (objectType == typeof(Toy));
}
public override object ReadJson(JsonReader reader,
Type objectType, object existingValue, JsonSerializer serializer)
{
// load the toy JSON object into a JObject
JObject jo = JObject.Load(reader);
// get the first (and only) property of the object
JProperty prop = jo.Properties().First();
// deserialize the value of that property (which is another
// object containing supplier and cost info) into a Toy instance
Toy toy = prop.Value.ToObject<Toy>();
// get the name of the property and add it to the newly minted toy
toy.Name = prop.Name;
return toy;
}
public override void WriteJson(JsonWriter writer,
object value, JsonSerializer serializer)
{
// If you need to serialize Toys back into JSON, then you'll need
// to implement this method. We can skip it for now.
throw new NotImplementedException();
}
}
List<Toy> toys = JsonConvert.DeserializeObject<List<Toy>>(json, new ToyConverter());
foreach (Toy toy in toys)
{
Console.WriteLine("toy: " + toy.Name);
Console.WriteLine("supplier: " + toy.Supplier);
Console.WriteLine("cost: " + toy.Cost + " (" + toy.Currency + ")");
Console.WriteLine();
}