Указатель NULL
- это тот, который указывает на никуда. Когда вы разыскиваете указатель p
, вы говорите «дайте мне данные в месте, хранящемся в« p ». Когда p
является нулевым указателем, местоположение, хранящееся в p
, является nowhere
, вы говорите «Дайте мне данные в месте« нигде ». Очевидно, он не может этого сделать, поэтому он выбрасывает NULL pointer exception
.
В общем, это потому, что что-то не было правильно инициализировано.
Я пошел вперед и использовал это. Дайте мне знать, если есть лучший способ.
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));
}
Другой вариант - создать собственный OneWayXmlNodeConverter
, наследующий от JsonConverter
, и вызвать SerializeObject
вместо SerializeXmlNode
следующим образом:
var json = JsonConvert.SerializeObject(xmlNode, new OneWayXmlNodeConverter());
Я называю это «One Way», потому что я предположим, что по умолчанию XmlNodeConverter
добавляет знак «@», чтобы он мог преобразовать обратно в XML из результирующего JSON.
Если вы включили источник JSON.NET
в свой проект (в отличие от только скомпилированной библиотеки ), простой способ создать OneWayXmlNodeConverter
- скопировать код XmlNodeConverter
, удалить жестко закодированный знак «@» в личном GetPropertyName
методе и сохранить его как OneWayXmlNodeConverter
.
Примечание. Я знаю, что ваш вопрос специфичен для «замены» знака «@», но связанный вариант Предотвращение этого вопроса отмечен как дубликат.
Мне потребовалось довольно много времени, чтобы найти правильный ответ, поэтому я решил поделиться:
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"}}}
Если JSON имеет отступ, это может работать:
Regex.Replace(result, @"(\s*)""@(.*)"":", @"$1""$2"":", RegexOptions.IgnoreCase);
Прошло некоторое время с момента ответа, но это может помочь кому-то. Поскольку у вас уже есть 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);
}
Сначала замените все «@» в вашем xml-содержимом некоторым заполнителем (в качестве примера {{at_the_rate}}). Затем используйте ниже код
JsonConvert.SerializeXmlNode(doc).Replace("@", "").Replace("{{at_the_rate}}", "@")
Я предлагаю использовать следующее регулярное выражение, это то же самое, что и @yieio, но улучшать, чтобы оставить содержимое без изменений и влиять только на имена свойств
var jString = Regex.Replace(
JsonConvert.SerializeXmlNode(content, Newtonsoft.Json.Formatting.None, true),
"(?<=(\\,\\\"|\\{\\\"))(@)(?!.*\\\":\\\\s )", String.Empty, System.Text.RegularExpressions.RegexOptions.IgnoreCase);
Regex не всегда работает отлично, когда контент имеет символ @ и, в первую очередь, это тоже будет заменено. поэтому я думаю, что (?<!:)(\"@)(?!.\":\\s )
может быть лучше.
"@
, например. <test attr=""@foo" />
приведет к {"test":{"attr":"\"foo"}}
.
– Aristoteles
22 July 2013 в 11:25
Если вы хотите получить доступ к значению атрибута из-за знака «@», выполните следующие действия:
Navigation["@Type"]
@
, например.<test attr="@foo" />
приведет к{"test":{"attr":"foo"}}
. – Aristoteles 22 July 2013 в 11:26