Saya mulai menggunakan Json.NET untuk mengkonversi string dalam format JSON ke objek atau sebaliknya. Saya tidak yakin dalam kerangka kerja Json.NET, apakah mungkin untuk mengubah string dalam JSON ke format XML dan sebaliknya?
Saya mulai menggunakan Json.NET untuk mengkonversi string dalam format JSON ke objek atau sebaliknya. Saya tidak yakin dalam kerangka kerja Json.NET, apakah mungkin untuk mengubah string dalam JSON ke format XML dan sebaliknya?
Jawaban:
Iya. Menggunakan kelas JsonConvert yang berisi metode pembantu untuk tujuan yang tepat ini:
// 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);
Dokumentasi di sini: Konversi antara JSON dan XML dengan Json.NET
Ya, Anda bisa melakukannya (saya lakukan) tetapi Waspadai beberapa paradoks saat mengkonversi, dan tangani dengan tepat. Anda tidak dapat secara otomatis menyesuaikan diri dengan semua kemungkinan antarmuka, dan ada dukungan bawaan yang terbatas dalam mengendalikan konversi - banyak struktur dan nilai JSON tidak dapat secara otomatis dikonversi dua arah. Ingatlah bahwa saya menggunakan pengaturan default dengan pustaka Newtonsoft JSON dan pustaka MS XML, sehingga jarak tempuh Anda dapat bervariasi:
{}
bersarang ATAU nested-array [ {} {} ...]
tergantung jika hanya ada satu atau lebih elemen XML anak. Anda akan mengkonsumsi dua ini secara berbeda dalam JavaScript, dll. Contoh XML yang berbeda sesuai dengan skema yang sama dapat menghasilkan struktur JSON yang berbeda dengan cara ini. Anda dapat menambahkan atribut json: Array = 'true' ke elemen Anda untuk mengatasinya dalam beberapa (tetapi tidak semua) kasus.Pembaruan baru mengubah ini (Terima kasih kepada Jon Story karena menunjukkannya): https://www.newtonsoft.com/json/help/html/T_Newtonsoft_Json_NullValueHandling.htm
Jangan ragu untuk menyebutkan masalah lain yang Anda perhatikan, saya telah mengembangkan rutinitas kebiasaan saya sendiri untuk mempersiapkan dan membersihkan string saat saya mengkonversi bolak-balik. Situasi Anda mungkin atau mungkin tidak meminta persiapan / pembersihan. Seperti StaxMan menyebutkan, situasi Anda mungkin sebenarnya mengharuskan Anda mengkonversi antara objek ... ini bisa memerlukan antarmuka yang sesuai dan banyak pernyataan kasus / dll untuk menangani peringatan yang saya sebutkan di atas.
Anda dapat melakukan konversi ini juga dengan .NET Framework:
JSON ke XML: dengan menggunakan System.Runtime.Serialization.Json
var xml = XDocument.Load(JsonReaderWriterFactory.CreateJsonReader(
Encoding.ASCII.GetBytes(jsonString), new XmlDictionaryReaderQuotas()));
XML ke JSON: dengan menggunakan 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 } };
}
Saya tidak yakin ada gunanya konversi seperti itu (ya, banyak yang melakukannya, tetapi kebanyakan untuk memaksa pasak persegi melalui lubang bundar) - ada ketidakcocokan impedansi struktural, dan konversi adalah lossy. Jadi saya akan merekomendasikan terhadap transformasi format ke format.
Tetapi jika Anda melakukannya, pertama-tama konversikan dari json ke objek, kemudian dari objek ke xml (dan sebaliknya untuk arah sebaliknya). Melakukan transformasi langsung mengarah pada keluaran yang buruk, hilangnya informasi, atau mungkin keduanya.
Terima kasih atas jawaban David Brown . Dalam kasus saya JSON.Net 3.5, metode konversi berada di bawah kelas statis 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);
Saya mencari waktu yang lama untuk menemukan kode alternatif untuk solusi yang diterima dengan harapan tidak menggunakan perakitan / proyek eksternal. Saya datang dengan berkat kode sumber proyek DynamicJson sebagai berikut :
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;
}
Catatan: Saya menginginkan XmlDocument daripada XElement untuk keperluan xPath. Juga, kode ini jelas hanya berjalan dari JSON ke XML, ada berbagai cara untuk melakukan yang sebaliknya.
Berikut adalah kode c # lengkap untuk mengonversi xml ke 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();
}
}
Untuk mengonversi string XML yang diberikan ke JSON, cukup panggil fungsi XmlToJSON () seperti di bawah ini.
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" }}
Coba fungsi ini. Saya baru saja menulis dan belum punya banyak kesempatan untuk mengujinya, tetapi tes pendahuluan saya menjanjikan.
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;
}
Berikut ini cuplikan sederhana yang mengubah XmlNode (secara rekursif) menjadi hashtable, dan mengelompokkan beberapa instance dari anak yang sama ke dalam array (sebagai ArrayList). Hashtable biasanya diterima untuk dikonversi ke JSON oleh sebagian besar pustaka 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 - perpustakaan open source yang tersedia untuk melakukan konversi Xml ke JSON dengan mudah dengan beberapa baris kode
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);
}
}
Periksa artikel CodeProject Project untuk bantuan tambahan.
Penafian: Saya penulis perpustakaan ini.
Saya memang suka kata David Brown tapi saya mendapat pengecualian berikut.
$exception {"There are multiple root elements. Line , position ."} System.Xml.XmlException
Salah satu solusinya adalah dengan memodifikasi file XML dengan elemen root tetapi itu tidak selalu diperlukan dan untuk aliran XML mungkin juga tidak mungkin. Solusi saya di bawah ini:
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);
}
}
}
}
Contoh XML yang menghasilkan kesalahan:
<parent>
<child>
Text
</child>
</parent>
<parent>
<child>
<grandchild>
Text
</grandchild>
<grandchild>
Text
</grandchild>
</child>
<child>
Text
</child>
</parent>
Saya telah menggunakan metode di bawah ini untuk mengkonversi JSON ke 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();
}
}
Dan
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();
}
Saya telah menggunakan kelas bernama Item untuk mewakili elemen
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; }
}
Berhasil....
Untuk mengonversi JSON
string untuk XML
mencoba ini:
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();
}
Untuk mengkonversi XML
ke JSON
mencoba ini:
public string XmlToJson(string xml)
{
XmlDocument doc = new XmlDocument();
doc.LoadXml(xml);
string jsonText = JsonConvert.SerializeXmlNode(doc);
return jsonText;
}
menggunakan perpustakaan pihak ketiga, alih-alih menulis kode sendiri untuk mem-parsing JSON atau XML String. Jika sekali pakai, cobalah untuk mengubahnya secara online. Json to Xml https://www.easycodeforall.com/Json2Xml.jsp Xml to Json https://www.easycodeforall.com/Xml2Json.jsp