Tôi bắt đầu sử dụng Json.NET để chuyển đổi một chuỗi ở định dạng JSON thành đối tượng hoặc ngược lại. Tôi không chắc chắn trong khung công tác Json.NET, có thể chuyển đổi một chuỗi trong JSON sang định dạng XML và ngược lại không?
Tôi bắt đầu sử dụng Json.NET để chuyển đổi một chuỗi ở định dạng JSON thành đối tượng hoặc ngược lại. Tôi không chắc chắn trong khung công tác Json.NET, có thể chuyển đổi một chuỗi trong JSON sang định dạng XML và ngược lại không?
Câu trả lời:
Đúng. Sử dụng lớp JsonConvert chứa các phương thức của trình trợ giúp cho mục đích chính xác này:
// To convert an XML node contained in string xml into a JSON string
XmlDocument doc = new XmlDocument();
doc.LoadXml(xml);
string jsonText = JsonConvert.SerializeXmlNode(doc);
// To convert JSON text contained in string json into an XML node
XmlDocument doc = JsonConvert.DeserializeXmlNode(json);
Tài liệu ở đây: Chuyển đổi giữa JSON và XML bằng Json.NET
Vâng, bạn có thể làm điều đó (tôi làm) nhưng hãy lưu ý một số nghịch lý khi chuyển đổi và xử lý phù hợp. Bạn không thể tự động tuân thủ tất cả các khả năng giao diện và có hỗ trợ tích hợp hạn chế trong việc kiểm soát chuyển đổi - nhiều cấu trúc và giá trị JSON không thể tự động được chuyển đổi theo cả hai cách. Hãy nhớ rằng tôi đang sử dụng các cài đặt mặc định với thư viện Newtonsoft JSON và thư viện MS XML, vì vậy số dặm của bạn có thể thay đổi:
{}
lồng nhau HOẶC mảng lồng nhau [ {} {} ...]
tùy thuộc vào nếu chỉ có một hoặc nhiều phần tử con XML. Bạn sẽ sử dụng hai cách khác nhau này trong JavaScript, v.v. Các ví dụ khác nhau về việc XML tuân thủ cùng một lược đồ có thể tạo ra các cấu trúc JSON thực sự khác nhau theo cách này. Bạn có thể thêm thuộc tính json: Array = 'true' vào phần tử của bạn để khắc phục điều này trong một số trường hợp (nhưng không nhất thiết là tất cả).Một bản cập nhật mới thay đổi điều này (Cảm ơn Jon Story đã chỉ ra nó): https://www.newtonsoft.com/json/help/html/T_Newtonsoft_Json_NullValueHandling.htmlm
Xin vui lòng đề cập đến bất kỳ vấn đề nào khác mà bạn nhận thấy, tôi đã phát triển các thói quen tùy chỉnh của riêng mình để chuẩn bị và làm sạch các chuỗi khi tôi chuyển đổi qua lại. Tình huống của bạn có thể hoặc không thể gọi để chuẩn bị / dọn dẹp. Như StaxMan đề cập, tình huống của bạn thực sự có thể yêu cầu bạn chuyển đổi giữa các đối tượng ... điều này có thể đòi hỏi các giao diện phù hợp và một loạt các báo cáo trường hợp / vv để xử lý các cảnh báo tôi đã đề cập ở trên.
Bạn cũng có thể thực hiện các chuyển đổi này với .NET Framework:
JSON sang XML: bằng cách sử dụng System.R.78.Serialization.Json
var xml = XDocument.Load(JsonReaderWriterFactory.CreateJsonReader(
Encoding.ASCII.GetBytes(jsonString), new XmlDictionaryReaderQuotas()));
XML sang JSON: bằng cách sử dụng System.Web.Script.Serialization
var json = new JavaScriptSerializer().Serialize(GetXmlData(XElement.Parse(xmlString)));
private static Dictionary<string, object> GetXmlData(XElement xml)
{
var attr = xml.Attributes().ToDictionary(d => d.Name.LocalName, d => (object)d.Value);
if (xml.HasElements) attr.Add("_value", xml.Elements().Select(e => GetXmlData(e)));
else if (!xml.IsEmpty) attr.Add("_value", xml.Value);
return new Dictionary<string, object> { { xml.Name.LocalName, attr } };
}
Tôi không chắc chắn có điểm trong chuyển đổi như vậy (vâng, nhiều người thực hiện nó, nhưng chủ yếu là buộc một chốt vuông qua lỗ tròn) - có sự không khớp trở kháng cấu trúc, và chuyển đổi bị mất. Vì vậy, tôi sẽ đề nghị chống lại các chuyển đổi định dạng thành định dạng như vậy.
Nhưng nếu bạn làm điều đó, trước tiên hãy chuyển đổi từ json sang đối tượng, sau đó từ đối tượng sang xml (và ngược lại cho hướng ngược lại). Thực hiện chuyển đổi trực tiếp dẫn đến đầu ra xấu xí, mất thông tin hoặc có thể cả hai.
Cảm ơn câu trả lời của David Brown . Trong trường hợp JSON.Net 3.5 của tôi, các phương thức chuyển đổi nằm trong lớp tĩnh JsonConvert:
XmlNode myXmlNode = JsonConvert.DeserializeXmlNode(myJsonString); // is node not note
// or .DeserilizeXmlNode(myJsonString, "root"); // if myJsonString does not have a root
string jsonString = JsonConvert.SerializeXmlNode(myXmlNode);
Tôi đã tìm kiếm trong một thời gian dài để tìm mã thay thế cho giải pháp được chấp nhận với hy vọng không sử dụng lắp ráp / dự án bên ngoài. Tôi đã đưa ra những điều sau nhờ vào mã nguồn của dự án DynamicJson :
public XmlDocument JsonToXML(string json)
{
XmlDocument doc = new XmlDocument();
using (var reader = JsonReaderWriterFactory.CreateJsonReader(Encoding.UTF8.GetBytes(json), XmlDictionaryReaderQuotas.Max))
{
XElement xml = XElement.Load(reader);
doc.LoadXml(xml.ToString());
}
return doc;
}
Lưu ý: Tôi muốn có XmlDocument thay vì XE đắp cho mục đích xPath. Ngoài ra, mã này rõ ràng chỉ đi từ JSON sang XML, có nhiều cách khác nhau để làm ngược lại.
Dưới đây là mã c # đầy đủ để chuyển đổi xml sang json
public static class JSon
{
public static string XmlToJSON(string xml)
{
XmlDocument doc = new XmlDocument();
doc.LoadXml(xml);
return XmlToJSON(doc);
}
public static string XmlToJSON(XmlDocument xmlDoc)
{
StringBuilder sbJSON = new StringBuilder();
sbJSON.Append("{ ");
XmlToJSONnode(sbJSON, xmlDoc.DocumentElement, true);
sbJSON.Append("}");
return sbJSON.ToString();
}
// XmlToJSONnode: Output an XmlElement, possibly as part of a higher array
private static void XmlToJSONnode(StringBuilder sbJSON, XmlElement node, bool showNodeName)
{
if (showNodeName)
sbJSON.Append("\"" + SafeJSON(node.Name) + "\": ");
sbJSON.Append("{");
// Build a sorted list of key-value pairs
// where key is case-sensitive nodeName
// value is an ArrayList of string or XmlElement
// so that we know whether the nodeName is an array or not.
SortedList<string, object> childNodeNames = new SortedList<string, object>();
// Add in all node attributes
if (node.Attributes != null)
foreach (XmlAttribute attr in node.Attributes)
StoreChildNode(childNodeNames, attr.Name, attr.InnerText);
// Add in all nodes
foreach (XmlNode cnode in node.ChildNodes)
{
if (cnode is XmlText)
StoreChildNode(childNodeNames, "value", cnode.InnerText);
else if (cnode is XmlElement)
StoreChildNode(childNodeNames, cnode.Name, cnode);
}
// Now output all stored info
foreach (string childname in childNodeNames.Keys)
{
List<object> alChild = (List<object>)childNodeNames[childname];
if (alChild.Count == 1)
OutputNode(childname, alChild[0], sbJSON, true);
else
{
sbJSON.Append(" \"" + SafeJSON(childname) + "\": [ ");
foreach (object Child in alChild)
OutputNode(childname, Child, sbJSON, false);
sbJSON.Remove(sbJSON.Length - 2, 2);
sbJSON.Append(" ], ");
}
}
sbJSON.Remove(sbJSON.Length - 2, 2);
sbJSON.Append(" }");
}
// StoreChildNode: Store data associated with each nodeName
// so that we know whether the nodeName is an array or not.
private static void StoreChildNode(SortedList<string, object> childNodeNames, string nodeName, object nodeValue)
{
// Pre-process contraction of XmlElement-s
if (nodeValue is XmlElement)
{
// Convert <aa></aa> into "aa":null
// <aa>xx</aa> into "aa":"xx"
XmlNode cnode = (XmlNode)nodeValue;
if (cnode.Attributes.Count == 0)
{
XmlNodeList children = cnode.ChildNodes;
if (children.Count == 0)
nodeValue = null;
else if (children.Count == 1 && (children[0] is XmlText))
nodeValue = ((XmlText)(children[0])).InnerText;
}
}
// Add nodeValue to ArrayList associated with each nodeName
// If nodeName doesn't exist then add it
List<object> ValuesAL;
if (childNodeNames.ContainsKey(nodeName))
{
ValuesAL = (List<object>)childNodeNames[nodeName];
}
else
{
ValuesAL = new List<object>();
childNodeNames[nodeName] = ValuesAL;
}
ValuesAL.Add(nodeValue);
}
private static void OutputNode(string childname, object alChild, StringBuilder sbJSON, bool showNodeName)
{
if (alChild == null)
{
if (showNodeName)
sbJSON.Append("\"" + SafeJSON(childname) + "\": ");
sbJSON.Append("null");
}
else if (alChild is string)
{
if (showNodeName)
sbJSON.Append("\"" + SafeJSON(childname) + "\": ");
string sChild = (string)alChild;
sChild = sChild.Trim();
sbJSON.Append("\"" + SafeJSON(sChild) + "\"");
}
else
XmlToJSONnode(sbJSON, (XmlElement)alChild, showNodeName);
sbJSON.Append(", ");
}
// Make a string safe for JSON
private static string SafeJSON(string sIn)
{
StringBuilder sbOut = new StringBuilder(sIn.Length);
foreach (char ch in sIn)
{
if (Char.IsControl(ch) || ch == '\'')
{
int ich = (int)ch;
sbOut.Append(@"\u" + ich.ToString("x4"));
continue;
}
else if (ch == '\"' || ch == '\\' || ch == '/')
{
sbOut.Append('\\');
}
sbOut.Append(ch);
}
return sbOut.ToString();
}
}
Để chuyển đổi một chuỗi XML đã cho thành JSON, chỉ cần gọi hàm XmlToJSON () như bên dưới.
string xml = "<menu id=\"file\" value=\"File\"> " +
"<popup>" +
"<menuitem value=\"New\" onclick=\"CreateNewDoc()\" />" +
"<menuitem value=\"Open\" onclick=\"OpenDoc()\" />" +
"<menuitem value=\"Close\" onclick=\"CloseDoc()\" />" +
"</popup>" +
"</menu>";
string json = JSON.XmlToJSON(xml);
// json = { "menu": {"id": "file", "popup": { "menuitem": [ {"onclick": "CreateNewDoc()", "value": "New" }, {"onclick": "OpenDoc()", "value": "Open" }, {"onclick": "CloseDoc()", "value": "Close" } ] }, "value": "File" }}
Hãy thử chức năng này. Tôi chỉ viết nó và không có nhiều cơ hội để kiểm tra nó, nhưng các thử nghiệm sơ bộ của tôi rất hứa hẹn.
public static XmlDocument JsonToXml(string json)
{
XmlNode newNode = null;
XmlNode appendToNode = null;
XmlDocument returnXmlDoc = new XmlDocument();
returnXmlDoc.LoadXml("<Document />");
XmlNode rootNode = returnXmlDoc.SelectSingleNode("Document");
appendToNode = rootNode;
string[] arrElementData;
string[] arrElements = json.Split('\r');
foreach (string element in arrElements)
{
string processElement = element.Replace("\r", "").Replace("\n", "").Replace("\t", "").Trim();
if ((processElement.IndexOf("}") > -1 || processElement.IndexOf("]") > -1) && appendToNode != rootNode)
{
appendToNode = appendToNode.ParentNode;
}
else if (processElement.IndexOf("[") > -1)
{
processElement = processElement.Replace(":", "").Replace("[", "").Replace("\"", "").Trim();
newNode = returnXmlDoc.CreateElement(processElement);
appendToNode.AppendChild(newNode);
appendToNode = newNode;
}
else if (processElement.IndexOf("{") > -1 && processElement.IndexOf(":") > -1)
{
processElement = processElement.Replace(":", "").Replace("{", "").Replace("\"", "").Trim();
newNode = returnXmlDoc.CreateElement(processElement);
appendToNode.AppendChild(newNode);
appendToNode = newNode;
}
else
{
if (processElement.IndexOf(":") > -1)
{
arrElementData = processElement.Replace(": \"", ":").Replace("\",", "").Replace("\"", "").Split(':');
newNode = returnXmlDoc.CreateElement(arrElementData[0]);
for (int i = 1; i < arrElementData.Length; i++)
{
newNode.InnerText += arrElementData[i];
}
appendToNode.AppendChild(newNode);
}
}
}
return returnXmlDoc;
}
Dưới đây là một đoạn mã đơn giản chuyển đổi XmlNode (đệ quy) thành hàm băm và nhóm nhiều trường hợp của cùng một đứa trẻ thành một mảng (dưới dạng ArrayList). Hashtable thường được chấp nhận để chuyển đổi thành JSON bởi hầu hết các thư viện JSON.
protected object convert(XmlNode root){
Hashtable obj = new Hashtable();
for(int i=0,n=root.ChildNodes.Count;i<n;i++){
object result = null;
XmlNode current = root.ChildNodes.Item(i);
if(current.NodeType != XmlNodeType.Text)
result = convert(current);
else{
int resultInt;
double resultFloat;
bool resultBoolean;
if(Int32.TryParse(current.Value, out resultInt)) return resultInt;
if(Double.TryParse(current.Value, out resultFloat)) return resultFloat;
if(Boolean.TryParse(current.Value, out resultBoolean)) return resultBoolean;
return current.Value;
}
if(obj[current.Name] == null)
obj[current.Name] = result;
else if(obj[current.Name].GetType().Equals(typeof(ArrayList)))
((ArrayList)obj[current.Name]).Add(result);
else{
ArrayList collision = new ArrayList();
collision.Add(obj[current.Name]);
collision.Add(result);
obj[current.Name] = collision;
}
}
return obj;
}
Cinchoo ETL - một thư viện mã nguồn mở có sẵn để thực hiện chuyển đổi Xml thành JSON dễ dàng với một vài dòng mã
Xml -> JSON:
using (var p = new ChoXmlReader("sample.xml"))
{
using (var w = new ChoJSONWriter("sample.json"))
{
w.Write(p);
}
}
JSON -> Xml:
using (var p = new ChoJsonReader("sample.json"))
{
using (var w = new ChoXmlWriter("sample.xml"))
{
w.Write(p);
}
}
Kiểm tra bài viết CodeProject cho một số trợ giúp bổ sung.
Tuyên bố miễn trừ trách nhiệm: Tôi là tác giả của thư viện này.
Tôi đã làm như David Brown nói nhưng tôi đã có ngoại lệ sau đây.
$exception {"There are multiple root elements. Line , position ."} System.Xml.XmlException
Một giải pháp sẽ là sửa đổi tệp XML bằng một phần tử gốc nhưng điều đó không phải lúc nào cũng cần thiết và đối với một luồng XML thì điều đó cũng không thể thực hiện được. Giải pháp của tôi dưới đây:
var path = Path.GetFullPath(Path.Combine(Environment.CurrentDirectory, @"..\..\App_Data"));
var directoryInfo = new DirectoryInfo(path);
var fileInfos = directoryInfo.GetFiles("*.xml");
foreach (var fileInfo in fileInfos)
{
XmlDocument doc = new XmlDocument();
XmlReaderSettings settings = new XmlReaderSettings();
settings.ConformanceLevel = ConformanceLevel.Fragment;
using (XmlReader reader = XmlReader.Create(fileInfo.FullName, settings))
{
while (reader.Read())
{
if (reader.NodeType == XmlNodeType.Element)
{
var node = doc.ReadNode(reader);
string json = JsonConvert.SerializeXmlNode(node);
}
}
}
}
Ví dụ XML tạo ra lỗi:
<parent>
<child>
Text
</child>
</parent>
<parent>
<child>
<grandchild>
Text
</grandchild>
<grandchild>
Text
</grandchild>
</child>
<child>
Text
</child>
</parent>
Tôi đã sử dụng các phương thức dưới đây để chuyển đổi JSON thành XML
List <Item> items;
public void LoadJsonAndReadToXML() {
using(StreamReader r = new StreamReader(@ "E:\Json\overiddenhotelranks.json")) {
string json = r.ReadToEnd();
items = JsonConvert.DeserializeObject <List<Item>> (json);
ReadToXML();
}
}
Và
public void ReadToXML() {
try {
var xEle = new XElement("Items",
from item in items select new XElement("Item",
new XElement("mhid", item.mhid),
new XElement("hotelName", item.hotelName),
new XElement("destination", item.destination),
new XElement("destinationID", item.destinationID),
new XElement("rank", item.rank),
new XElement("toDisplayOnFod", item.toDisplayOnFod),
new XElement("comment", item.comment),
new XElement("Destinationcode", item.Destinationcode),
new XElement("LoadDate", item.LoadDate)
));
xEle.Save("E:\\employees.xml");
Console.WriteLine("Converted to XML");
} catch (Exception ex) {
Console.WriteLine(ex.Message);
}
Console.ReadLine();
}
Tôi đã sử dụng lớp có tên là Item để biểu diễn các phần tử
public class Item {
public int mhid { get; set; }
public string hotelName { get; set; }
public string destination { get; set; }
public int destinationID { get; set; }
public int rank { get; set; }
public int toDisplayOnFod { get; set; }
public string comment { get; set; }
public string Destinationcode { get; set; }
public string LoadDate { get; set; }
}
Nó hoạt động ....
Để chuyển đổi JSON
chuỗi để XML
thử điều này:
public string JsonToXML(string json)
{
XDocument xmlDoc = new XDocument(new XDeclaration("1.0", "utf-8", ""));
XElement root = new XElement("Root");
root.Name = "Result";
var dataTable = JsonConvert.DeserializeObject<DataTable>(json);
root.Add(
from row in dataTable.AsEnumerable()
select new XElement("Record",
from column in dataTable.Columns.Cast<DataColumn>()
select new XElement(column.ColumnName, row[column])
)
);
xmlDoc.Add(root);
return xmlDoc.ToString();
}
Để chuyển đổi XML
để JSON
thử điều này:
public string XmlToJson(string xml)
{
XmlDocument doc = new XmlDocument();
doc.LoadXml(xml);
string jsonText = JsonConvert.SerializeXmlNode(doc);
return jsonText;
}
sử dụng thư viện của bên thứ ba, thay vì viết mã riêng để phân tích chuỗi JSON hoặc XML. Nếu nó sử dụng một lần, hãy thử chuyển đổi trực tuyến. Json đến Xml https://www.easycodeforall.com/Json2Xml.jsp Xml sang Json https://www.easycodeforall.com/Xml2Json.jsp