在使用C#的Windows Phone应用中,我尝试使用以下结构反序列化一些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"
} }
]
这是玩具列表,其中的玩具(风筝,拼图,球)的名称事先未知。我对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);
我认为类似以下内容的方法可能会起作用,但如果该玩具有效(并且无效),我将丢失该玩具的名称:
public class Toy
{
public string supplier { get; set; }
public string currency { get; set; }
public string cost { get; set; }
}
List<Toy> toyList = (List<Toy>) JsonConvert.DeserializeObject(rawJSON, typeof(List<Toy>));
有什么建议吗?
你近了 如果您Toy
在问题中定义班级,则可以反序列化为List<Dictionary<string, Toy>>
。因此,每个玩具实际上由一个Dictionary
具有单个条目的a表示。该Key
是玩具的名称,Value
是Toy
信息。
这是一个演示:
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: kite
supplier: ABC
cost: 7.98 (GBP)
toy: puzzle
supplier: DEF
cost: 7.98 (USD)
toy: ball
supplier: DEF
cost: 5.49 (USD)
诚然,这种解决方案有点“笨拙”,因为最好将玩具的名称包含在Toy
类本身中,而不要进行干预Dictionary
。有两种方法可以解决此问题。一种方法是Name
在Toy
类上添加一个属性,将其反序列化为与上述相同的结构,然后进行一些后期处理,以将名称从每个名称移至相应的名称,Dictionary
并在此过程中Toy
构建一个新名称List<Toy>
。第二种方法是创建一个自定义,JsonConverter
以在反序列化期间处理此转换。如果您愿意,我很乐于演示这些替代方法中的任何一种。请让我知道。如果您只需要快捷的方法,那么上面的方法应该可以解决。
使用自定义JsonConverter的替代方法
这种方法有点“清洁”,因为我们可以将所有Toy
信息放在一个强类型的对象上,并且将所有反序列化逻辑保持分开,以免使主代码混乱。
首先,我们需要更改您的Toy
课程以为其提供Name
属性。
class Toy
{
public string Name { get; set; }
public string Supplier { get; set; }
public string Currency { get; set; }
public decimal Cost { get; set; }
}
接下来,我们创建一个继承自的类JsonConverter
。
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();
}
}
要使用转换器,我们只需要创建一个实例并将其传递给即可DeserializeObject<T>()
。现在有了转换器,我们可以直接反序列化为List<Toy>
,这很自然。
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();
}
您会注意到,它给出的输出与上一个示例完全相同,但是代码更加简洁。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句