使用C#将JSON转化为class
要想将JSON转化成class,首先要观察一下JSON文件,然后自定义一个和JSON格式一样的类,比如,JSON文件是这样的:
{
"@name":"Alice",
"gender":"female",
"age":"20",
"friends":[
{
"name":"Bob",
"hobby":"coding"
},
{
"name":"Charles",
"hobby":"swimming"
}
]
}
我们就可以将类定义为
public class Student{
[JsonProperty("@name")]
public string Name { get; set; }
public string Gender { get; set; }
public int Age { get; set; }
public List<Friend> Friends { get; set; }
public Student() { }
}
public class Friend{
public string Name { get; set; }
public string Hobby { get; set; }
public Friend() { }
}
然后在上一节中,我们简单介绍了一下将XML转化成JSON,现在我们把转化的函数改进一下:
public Studnet XmlStringToJson(string xml)
{
XmlDocument doc = new XmlDocument();
doc.LoadXml(xml);
string json = JsonConvert.SerializeXmlNode(doc);
Student student= JsonConvert.DeserializeObject<Student>(json);
return student;
}
可以发现,我们把转换后的json字符串反序列化为了Student对象。
但是别激动,还有很多坑。。。。
仔细观察一下,在数据中,我们有一个属性名字为@name,但是C#是没办法识别到@符号的,在parsing中会直接忽略掉这个属性以及它的值,打印出来就啥都没有,所以我们需要建立一个mapping,将@name这个名字与我们在类中定义的想要装载它的Name属性对应起来,这样的话,就告诉了parser只要碰到@name统统扔到Student.Name中来。
再观察一下,数据中Student有一个friends的数组,在JSON中,只要有方括号,一定是数组(JSON Array),花括号一定是对象(JSON Object)。
现在假设我们的Student也是一个数组,有好多Student,但是有个别Student只有一个朋友,于是乎,这唯一的一个朋友就被parser解析成了对象,用花括号包着。
我们先改进一下变成数组以后的反序列化:
var students= JsonConvert.DeserializeObject<List<Student>>(json);
然后执行一下就光荣报错了。
它会提示你,恩,你这个Object朋友不能转化为Array朋友们,然后可以用JsonArrayAttribute什么巴拉巴拉的强制转化。
强转是可以的,但是一堆Student,一会儿是Object朋友,一会儿是Array朋友们,到底谁转谁这就很麻烦了,查了各种资料以后,发现还真有人也遇到过这样的问题,以下是解决方案地址,看作者叫Brian Rogers的那个答案:
https://stackoverflow.com/questions/18994685/how-to-handle-both-a-single-item-and-an-array-for-the-same-property-using-json-n
于是我把它SingleOrArrayConverter这个类的代码原封不动粘了过来,然后再像他那样给Friends属性如下所示加上:
[JsonProperty("Friend")]
[JsonConverter(typeof(SingleOrArrayConverter<Friend>))]
public List<Friend> Friends{ get; set; }
然后就work啦~
注意SingleOrArrayConverter后面尖括号里的类型一定要和它下面类里定义的属性Friends类型相反,一个是List一个是Object。