一、JSON字符串的成串规则
1)JSON规则中有6中值类型Object、Array、String、Integer、Boolean、Float
2)值类型Object中可以放置任意个键值对,用大括号包住,值可以是中6中类型中的任何一种
3)值类型Array中可以放置任意个值,用方括号包住,值可以是中6中类型中的任何一种
4)值类型String、Integer、Boolean、Float
5)一个完整的有效JSON字符串,是一个Object值或一个Array值
判断一个字符串是否为有效的JSON字符串可以在BEJSON网(http://www.bejson.com/)上进行校验。
二、代码设计思路
因为一个有效的JSON字符串,是一个Object值或一个Array值,而这两个值中,又可以嵌套进JSON中所有的六种值类型,因此对这两种值需要特别加以讨论。
实现将JSON转换为XML格式的函数,被放置在类JSON2XML中的静态方法WriteJsonToXml中
public static void WriteJsonToXml(string path, string json)
path为XML保存到的文件路径,json为被转换的JSON字符串。
该方法的实现思路为:
1)判断path指向的文件是否存在,如果存在,则删除原文件
2)通过XmlTextWriter建立XML文档,编码方案使用GBK
3)设置生成的XML文档绑定json2xml.dtd进行校验
4)判断JSON字符串是Object类型还是Array类型,分类讨论,若为Object则调用AnalyseJsonObject函数解析,若为Array则调用AnalyseJsonArray函数解析。
函数AnalyseJsonObject和函数AnalyseJsonArray分别用来解析Object值和Array值
public static void AnalyseJsonObject(XmlTextWriter writer, JToken jt)
public static void AnalyseJsonArray(XmlTextWriter writer, JToken jt)
解析到嵌套的Object和Array值时,会继续递归调用这两个函数进一步解析
三、JSON2XML代码
class JSON2XML
{
/// <summary>
/// 将JSON格式的内容写入到地址为address的XML中
/// </summary>
/// <param name="path">要存入的文件地址</param>
/// <param name="json">源JSON字符串</param>
public static void WriteJsonToXml(string path, string json)
{
//如果存在同名文件先删除
if (File.Exists(path))
{
File.Delete(path);
}
//建立XML文档
XmlTextWriter writer =
new XmlTextWriter(path, System.Text.Encoding.GetEncoding("GBK"));
writer.Formatting = System.Xml.Formatting.Indented;
writer.WriteStartDocument();
writer.WriteDocType(
"JSON2XML", "-//Tsybius//JSON2XML//EN", "json2xml.dtd", null);
writer.WriteComment("这个XML文档中存储了一个JSON格式的信息");
writer.WriteStartElement("JSON2XML");
//递归遍历JSON中的项并写入到XML中
JToken jp = JToken.Parse(json);
if (jp.Type == JTokenType.Object) //JSON为一个Object的情况
{
AnalyseJsonObject(writer, jp);
}
else if (jp.Type == JTokenType.Array) //JSON为一个Array的情况
{
AnalyseJsonArray(writer, jp);
}
writer.WriteEndElement();
writer.WriteEndDocument();
writer.Close();
//XML文档创建结束
}
/// <summary>
/// 将一段JSON格式字符串写入到XML文件中
/// </summary>
/// <param name="writer">XML编写器</param>
/// <param name="json">JSON字符串</param>
public static void AnalyseJsonObject(XmlTextWriter writer, JToken jt)
{
writer.WriteStartElement("JsonObject", "");
//遍历读取到的JSON字符串
foreach (JProperty jtemp in jt.Children())
{
//根据读入的不同数据类型分类讨论
switch (jtemp.Value.Type)
{
case JTokenType.Object:
{
writer.WriteStartElement("JsonObject", "");
writer.WriteAttributeString("Name", jtemp.Name.ToString());
AnalyseJsonObject(writer, jtemp.Value);
writer.WriteEndElement();
}
break;
case JTokenType.Array:
{
writer.WriteStartElement("JsonArray", "");
writer.WriteAttributeString("Name", jtemp.Name.ToString());
AnalyseJsonArray(writer, jtemp.Value);
writer.WriteEndElement();
}
break;
case JTokenType.String:
{
writer.WriteStartElement("JsonString", "");
writer.WriteAttributeString("Name", jtemp.Name.ToString());
writer.WriteAttributeString("Value", jtemp.Value.ToString());
writer.WriteEndElement();
}
break;
case JTokenType.Boolean:
{
writer.WriteStartElement("JsonBoolean", "");
writer.WriteAttributeString("Name", jtemp.Name.ToString());
writer.WriteAttributeString("Value", jtemp.Value.ToString());
writer.WriteEndElement();
}
break;
case JTokenType.Integer:
{
writer.WriteStartElement("JsonInteger", "");
writer.WriteAttributeString("Name", jtemp.Name.ToString());
writer.WriteAttributeString("Value", jtemp.Value.ToString());
writer.WriteEndElement();
}
break;
case JTokenType.Float:
{
writer.WriteStartElement("JsonFloat", "");
writer.WriteAttributeString("Name", jtemp.Name.ToString());
writer.WriteAttributeString("Value", jtemp.Value.ToString());
writer.WriteEndElement();
}
break;
default:
{
writer.WriteStartElement("Default", "");
writer.WriteAttributeString("Name", jtemp.Name.ToString());
writer.WriteAttributeString("Value", jtemp.Value.ToString());
writer.WriteEndElement();
}
break;
}
}
writer.WriteEndElement();
}
/// <summary>
/// 将一段JSON格式Array内容写入到XML文件中
/// </summary>
/// <param name="writer">XML编写器</param>
/// <param name="json">JSON字符串</param>
public static void AnalyseJsonArray(XmlTextWriter writer, JToken jt)
{
writer.WriteStartElement("JsonArray", "");
for (int i = 0; i < jt.Count(); i++)
{
switch (jt[i].Type)
{
case JTokenType.Object:
{
writer.WriteStartElement("ArrayItem", "");
writer.WriteAttributeString("Type", "Object");
AnalyseJsonObject(writer, jt[i]);
writer.WriteEndElement();
}
break;
case JTokenType.Array:
{
writer.WriteStartElement("ArrayItem", "");
writer.WriteAttributeString("Type", "Array");
JProperty jptemp = new JProperty("ArrayItem", jt[i]);
AnalyseJsonArray(writer, jt[i]);
writer.WriteEndElement();
}
break;
case JTokenType.String:
{
writer.WriteStartElement("ArrayItem", "");
writer.WriteAttributeString("Type", "String");
writer.WriteAttributeString("Value", jt[i].ToString());
writer.WriteEndElement();
}
break;
case JTokenType.Boolean:
{
writer.WriteStartElement("ArrayItem", "");
writer.WriteAttributeString("Type", "Boolean");
writer.WriteAttributeString("Value", jt[i].ToString());
writer.WriteEndElement();
}
break;
case JTokenType.Integer:
{
writer.WriteStartElement("ArrayItem", "");
writer.WriteAttributeString("Type", "Integer");
writer.WriteAttributeString("Value", jt[i].ToString());
writer.WriteEndElement();
}
break;
case JTokenType.Float:
{
writer.WriteStartElement("ArrayItem", "");
writer.WriteAttributeString("Type", "Float");
writer.WriteAttributeString("Value", jt[i].ToString());
writer.WriteEndElement();
}
break;
default:
{
writer.WriteStartElement("ArrayItem", "");
writer.WriteAttributeString("Type", "Default");
writer.WriteAttributeString("Value", jt[i].ToString());
writer.WriteEndElement();
}
break;
}
}
writer.WriteEndElement();
}
}
四、调用示例代码
调用函数需要使用一个辅助的工具类FileHelper,这个类中有两个函数
public static string ReadFromFile(string path)
public static void WriteToFile(string path, string content)
ReadFromFile函数从文件中读取内容到字符串
WriteToFile函数将字符串存储到路径为path的文件中
/// <summary>
/// 文件帮助类:读取文件中内容到字符串,将字符串中内容输出到文件
/// </summary>
class FileHelper
{
public static void WriteToFile(string path, string content)
{
//需要 using System.IO
StreamWriter sw = new StreamWriter(path, false, System.Text.Encoding.UTF8);
sw.Write(content);
sw.Close();
sw.Dispose();
}
public static string ReadFromFile(string path)
{
//需要 using System.IO
StreamReader sr = File.OpenText(path);
return sr.ReadToEnd();
}
}
Main函数的调用代码如下:
class Program
{
static void Main(string[] args)
{
//写入信息到文件
FileHelper.WriteToFile("a.txt", "1234");
//从文件JsonTest.txt中读取信息
string sJsonText1 = FileHelper.ReadFromFile("JsonTest1.txt");
string sJsonText2 = FileHelper.ReadFromFile("JsonTest2.txt");
//将读取的json文本转化后存储到XML中
JSON2XML.WriteJsonToXml("test1.xml", sJsonText1);
JSON2XML.WriteJsonToXml("test2.xml", sJsonText2);
}
}
其中,JsonTest1.txt和JsonTest1.txt是两个存储了两个JSON格式字符串的文件。
五、调用结果
JsonTest1.txt中内容如下:
{
"Name": "Tsybius",
"Age": 23,
"Sex_is_Male": true,
"Partner": {
"Partner_Name": "Galatea",
"Partner_Age": 21,
"Sex_is_Male": false
},
"Achievement": [
{
"Achvm1": "Achv1",
"Prize1": 5000
},
{
"Achvm2": "Achv2",
"Prize2": 5000
},
{
"Achvm3": "Achv3",
"Prize3": 5000
}
],
"OtherParament": [
"abcd",
1234,
true,
[
"abcd",
1234,
true
]
]
}
根据Main函数中的代码,转化后到test1.xml中,XML中内容如下:
<?xml version="1.0" encoding="gb2312"?>
<!DOCTYPE JSON2XML PUBLIC "-//Tsybius//JSON2XML//EN" "json2xml.dtd">
<!--这个XML文档中存储了一个JSON格式的信息-->
<JSON2XML>
<JsonObject>
<JsonString Name="Name" Value="Tsybius" />
<JsonInteger Name="Age" Value="23" />
<JsonBoolean Name="Sex_is_Male" Value="True" />
<JsonObject Name="Partner">
<JsonObject>
<JsonString Name="Partner_Name" Value="Galatea" />
<JsonInteger Name="Partner_Age" Value="21" />
<JsonBoolean Name="Sex_is_Male" Value="False" />
</JsonObject>
</JsonObject>
<JsonArray Name="Achievement">
<JsonArray>
<ArrayItem Type="Object">
<JsonObject>
<JsonString Name="Achvm1" Value="Achv1" />
<JsonInteger Name="Prize1" Value="5000" />
</JsonObject>
</ArrayItem>
<ArrayItem Type="Object">
<JsonObject>
<JsonString Name="Achvm2" Value="Achv2" />
<JsonInteger Name="Prize2" Value="5000" />
</JsonObject>
</ArrayItem>
<ArrayItem Type="Object">
<JsonObject>
<JsonString Name="Achvm3" Value="Achv3" />
<JsonInteger Name="Prize3" Value="5000" />
</JsonObject>
</ArrayItem>
</JsonArray>
</JsonArray>
<JsonArray Name="OtherParament">
<JsonArray>
<ArrayItem Type="String" Value="abcd" />
<ArrayItem Type="Integer" Value="1234" />
<ArrayItem Type="Boolean" Value="True" />
<ArrayItem Type="Array">
<JsonArray>
<ArrayItem Type="String" Value="abcd" />
<ArrayItem Type="Integer" Value="1234" />
<ArrayItem Type="Boolean" Value="True" />
</JsonArray>
</ArrayItem>
</JsonArray>
</JsonArray>
</JsonObject>
</JSON2XML>
JsonTest2.txt中内容如下:
[
1,
2,
[
1,
2,
3
]
]
根据Main函数中的代码,转化后到test2.xml中,XML中内容如下:
<?xml version="1.0" encoding="gb2312"?>
<!DOCTYPE JSON2XML PUBLIC "-//Tsybius//JSON2XML//EN" "json2xml.dtd">
<!--这个XML文档中存储了一个JSON格式的信息-->
<JSON2XML>
<JsonArray>
<ArrayItem Type="Integer" Value="1" />
<ArrayItem Type="Integer" Value="2" />
<ArrayItem Type="Array">
<JsonArray>
<ArrayItem Type="Integer" Value="1" />
<ArrayItem Type="Integer" Value="2" />
<ArrayItem Type="Integer" Value="3" />
</JsonArray>
</ArrayItem>
</JsonArray>
</JSON2XML>
六、校验XML文件用的DTD文件-json2xml.dtd
json2xml.dtd可以用来校验本程序生成的XML文件
<!--文件List.xml的DTD文档-->
<!--List:根节点,根节点包括且仅包括一个JsonObject或JsonArray-->
<!ELEMENT JSON2XML (JsonObject | JsonArray)+>
<!--JsonArray:Json中的Array,包括零个或多个数组元素-->
<!ELEMENT JsonArray (ArrayItem | EMPTY)*>
<!ATTLIST JsonArray Name CDATA #IMPLIED>
<!--ArrayItem:Json中Array的一个元素-->
<!ELEMENT ArrayItem (JsonObject | JsonArray | EMPTY)*>
<!ATTLIST ArrayItem Type CDATA #IMPLIED>
<!ATTLIST ArrayItem Value CDATA #IMPLIED>
<!--JsonObject:Json中的Object,包括多组键值对-->
<!ELEMENT JsonObject (
JsonObject | JsonArray | JsonString |
JsonBoolean | JsonInteger | JsonFloat | EMPTY)*>
<!ATTLIST JsonObject Name CDATA #IMPLIED>
<!--JsonString:Json中的String型数据-->
<!ELEMENT JsonString EMPTY>
<!ATTLIST JsonString Name CDATA #IMPLIED>
<!ATTLIST JsonString Value CDATA #IMPLIED>
<!--JsonBoolean:Json中的Boolean型数据-->
<!ELEMENT JsonBoolean EMPTY>
<!ATTLIST JsonBoolean Name CDATA #IMPLIED>
<!ATTLIST JsonBoolean Value CDATA #IMPLIED>
<!--JsonInteger:Json中的Integer型数据-->
<!ELEMENT JsonInteger EMPTY>
<!ATTLIST JsonInteger Name CDATA #IMPLIED>
<!ATTLIST JsonInteger Value CDATA #IMPLIED>
<!--JsonFloat:Json中的Float型数据-->
<!ELEMENT JsonFloat EMPTY>
<!ATTLIST JsonFloat Name CDATA #IMPLIED>
<!ATTLIST JsonFloat Value CDATA #IMPLIED>
<!--文档结束-->