2011-09-02 44 views
7

JSON.NET框架可以將XML轉換爲JSON,但它使用JSON中的@符號作爲屬性。我寧願刪除它之前發送到視圖。對此最好的方法是什麼?JSON.NET和替換@登錄XML到JSON對話

我知道我可以直接替換,但@字符可能在某處相關,不應該被替換。有這樣的正則表達式嗎?

public ActionResult Layout() 
{ 
    var xml = new XmlDocument(); 
    xml.XmlResolver = null; 
    xml.Load(Server.MapPath("~/App_Data/Navigation.xml")); 
    return Content(JsonConvert.SerializeXmlNode(xml, Newtonsoft.Json.Formatting.Indented)); 
} 
{ 
    "Layout": { 
    "Navigation": [ 
     { 
     "@Type": "Menu", 
     "@Title": "Dashboard" 
     }, 
     { 
     "@Type": "Menu", 
     "@Route": "Events", 
     "@Title": "Events", 
     "Navigation": { 
      "@Type": "Action", 
      "@Route": "Event", 
      "@Title": "+ Add Event", 
      "@Order": "1", 
      "Navigation": { 
      "@Type": "Item", 
      "@Route": "Event", 
      "@Name": "Event", 
      "Navigation": [ 
       { 
       "@Route": "Pools", 
       "@Type": "SubNavigation", 
       "@Name": "Pools" 
       }, 
       { 
       "@Route": "Brackets", 
       "@Type": "SubNavigation", 
       "@Name": "Brackets" 
       } 
      ] 
      } 
     } 
     } 
    ] 
    } 
} 

回答

10

我繼續用這個。讓我知道是否有更好的方法。

public ActionResult Layout() 
{ 
    var xml = new XmlDocument(); 
    xml.XmlResolver = null; 
    xml.Load(Server.MapPath("~/App_Data/Navigation.xml")); 

    var jsonText = JsonConvert.SerializeXmlNode(xml, Newtonsoft.Json.Formatting.Indented); 
    return Content(Regex.Replace(jsonText, "(?<=\")(@)(?!.*\":\\s)", string.Empty, RegexOptions.IgnoreCase)); 
} 
+1

F你知道,那是@符號將在JSON出現的唯一場所,工作與string.replace更快或更大的文件 – andryuha

+0

正如@yieio提到的,這仍然不適合工作以'@'開頭的值,例如''會產生'{「test」:{「attr」:「foo」}}'。 – Aristoteles

2

正則表達式並不總是很好,當內容有@字符時,並且首先會被替換。 所以我覺得(?<!:)(\"@)(?!.\":\\s)可能會更好。

+0

對於以「@」開頭的值,這仍然不起作用,例如''會導致'{「test」:{「attr」:「\」foo「}} '。 – Aristoteles

+0

@Aristoteles檢查我的正則表達式,它基於上述內容,但不修改內容 –

2

另一個選擇是創建自己的OneWayXmlNodeConverterJsonConverter繼承和調用SerializeObject,而不是SerializeXmlNode這樣的:

var json = JsonConvert.SerializeObject(xmlNode, new OneWayXmlNodeConverter()); 

我把它稱爲「單向」,因爲我認爲默認XmlNodeConverter添加「@」符號所以它可以從生成的JSON轉換回XML。

如果您在您的項目中JSON.NET源(而不是僅僅編譯庫),一個簡單的方法來創建OneWayXmlNodeConverter是複製XmlNodeConverter代碼,去掉硬編碼「@」符號私人GetPropertyName方法,並將其另存爲OneWayXmlNodeConverter

注意:我知道您的問題是「替換」「@」符號,但此問題的鏈接Preventing變體標記爲重複。

+0

您的建議非常有趣,但是您嘗試過嗎? 當我試圖複製XmlNodeConverter代碼時,我發現它很大程度上依賴於內部接口和類,所以我無法完成您的建議。 你是否設法讓它起作用? –

+1

@PolaEdward我在項目中包含了Json.Net源代碼,所以我能夠使用內部。我會更新我的答案,因爲你是對的,如果你只是使用圖書館,它*不那麼容易:-) – dalenewman

+0

好,更新答案總是推薦:) 其實我最終意識到我有嵌入牛頓軟件的代碼,以便能夠編輯它,堅持一個特定的版本,並從作者失去所有未來的更新,或使用正則表達式,我決定使用正則表達式 –

1

,我建議使用下面的正則表達式,它一樣@yieio提供的,而是提升到離開內容是沒有任何修改,並且隻影響屬性名稱

var jString = Regex.Replace(
JsonConvert.SerializeXmlNode(content, Newtonsoft.Json.Formatting.None, true), 
"(?<=(\\,\\\"|\\{\\\"))(@)(?!.*\\\":\\\\s)", String.Empty, System.Text.RegularExpressions.RegexOptions.IgnoreCase); 
+0

當我嘗試這個它不起作用,即。它似乎沒有改變任何東西。 會導致{「test」:{「@ attr」:「foo」}}。 –

0

如果您要訪問的值因爲「@」符號的屬性,請執行下列操作:

Navigation["@Type"] 
+0

是的,但是正因爲如此,在JSON上獲取屬性時性能會下降 – Jacks

0

已經過了一段時間,因爲這種反應,但這可能仍幫助別人。 由於您已經擁有XMLDocument,因此可以在序列化之前刪除並轉換屬性。我嘗試刪除屬性或將它們轉換爲元素。

public static void RemoveAllAttributes(XmlDocument xmlDocument) 
{ 
    if (xmlDocument == null || !xmlDocument.HasChildNodes) return; 

    foreach (var xmlElement in xmlDocument.SelectNodes(".//*").Cast<XmlElement>().Where(xmlElement => xmlElement.HasAttributes)) 
    { 
      xmlElement.Attributes.RemoveAll(); 
    } 
} 

public static void ElementifyAllAttributes(XmlDocument xmlDocument) 
{ 
    if (xmlDocument == null || !xmlDocument.HasChildNodes) return; 

    foreach (var xmlElement in xmlDocument.SelectNodes(".//*").Cast<XmlElement>().Where(xmlElement => xmlElement.HasAttributes)) 
    { 
     foreach (XmlAttribute xmlAttribute in xmlElement.Attributes) 
     { 
      xmlElement.AppendChild(xmlDocument.CreateElement(xmlAttribute.Name)).InnerText = xmlAttribute.Value; 
     } 

     xmlElement.Attributes.RemoveAll(); 
    } 
} 

然後;

private static string XmlToJson(XmlDocument xmlDocument) 
{ 
    if (xmlDocument == null) return null; 

    //Remove xml declaration 
    xmlDocument.RemoveChild(xmlDocument.FirstChild); 

    //Convert attributes to elements 
    ElementifyAllAttributes(xmlDocument); 

    return JsonConvert.SerializeXmlNode(xmlDocument, Formatting.None, false); 
} 
1

如果JSON是縮進,這可能是工作:

Regex.Replace(result, @"(\s*)""@(.*)"":", @"$1""$2"":", RegexOptions.IgnoreCase); 
+0

已證實可以工作,因爲它不會影響屬性內容中的@符號,無論是在開始,中間還是末尾。 –

6

我花了好半天才找到正確的答案,所以我想我會分享:

var xDocument = XDocument.Parse("<xml><a attr=\"b\">c</a></xml>"); 
var builder = new StringBuilder(); 
JsonSerializer.Create().Serialize(new CustomJsonWriter(new StringWriter(builder)), xDocument); 
var serialized = builder.ToString(); 

public class CustomJsonWriter : JsonTextWriter 
{ 
    public CustomJsonWriter(TextWriter writer): base(writer){} 

    public override void WritePropertyName(string name) 
    { 
     if (name.StartsWith("@") || name.StartsWith("#")) 
     { 
      base.WritePropertyName(name.Substring(1)); 
     } 
     else 
     { 
      base.WritePropertyName(name); 
     } 
    } 
} 

輸出:

{"xml":{"a":{"attr":"b","text":"c"}}} 
+0

這是最正確和最簡單的解決方案...重載轉換器將需要更多的工作來考慮所有情況。 – Maxim

0

第一次重複使用某個佔位符在您的xml內容中全部「@」(例如{{at_the_rate}})。然後使用下面的代碼

JsonConvert.SerializeXmlNode(doc).Replace("@", "").Replace("{{at_the_rate}}", "@") 
+0

我希望你明白如果你的數據有「{{at_the_rate}}」會發生什麼。 – Maxim