JSON.NET and Replacing @ Sign in XML to JSON converstion
It took me quite a while to find the right answer, so I thought I'd share:
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);
}
}
}
Output:
{"xml":{"a":{"attr":"b","text":"c"}}}
Another option is to create your own OneWayXmlNodeConverter
inheriting from JsonConverter
and call SerializeObject
instead of SerializeXmlNode
like this:
var json = JsonConvert.SerializeObject(xmlNode, new OneWayXmlNodeConverter());
I call it "One Way" because I assume the default XmlNodeConverter
adds the "@" sign so it can convert back to XML from the resulting JSON.
If you include the JSON.NET
source in your project (as opposed to just the compiled library), an easy way to create the OneWayXmlNodeConverter
is to copy the XmlNodeConverter
code, remove the hard-coded "@" sign in the private GetPropertyName
method, and save it as OneWayXmlNodeConverter
.
Note: I know that your question is specific to "replacing" the "@" sign, but the linked Preventing variation of this question is marked as duplicate.
The Regex not always work great,when content has the @ character and in the first place,that will be replace too.
so I think(?<!:)(\"@)(?!.\":\\s )
may be better.
I went ahead and used this. Let me know if there is a better way.
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));
}