Нужно сохранять конечные нули при преобразовании из JObject в XDocument

У меня довольно простой запрос. Я создаю объект json в С#. У меня есть некоторые свойства, которые удваиваются. Первоначально я создал xml и отформатировал эти значения, чтобы иметь соответствующее количество конечных нулей после десятичной точки. Теперь я создаю json и xml. Я генерирую json, используя LINQ to JSON. Затем я создаю и XDocument, используя JSONConvert. Но проблема в том, что если я поместил двойное значение в объект JObject как объект, а не форматированную строку, я потеряю конечные нули, чем если бы я сохранил его как строку. Вот пример кода:

****** value = 1.0;
string stringVal = "1.000";
JObject test = new JObject(new JProperty("sta", new JObject( new JProperty("@*********", value), new JProperty("@valString", stringVal) )));
var testXml = JsonConvert.DeserializeXNode(test.ToString());

Я понимаю, что могу просто пройти через созданные JObjects и вытащить значение и отформатировать его в строке вручную с помощью кода. Но есть ли способ, с помощью которого конвертер может обрабатывать значения с определенным форматом. Поэтому вместо того, чтобы

Я хочу получить,

Надеюсь, я хорошо объяснил эту проблему. Я просмотрел методы Deserialize, но у них просто есть другие опции для выбора имени корневого элемента и того, нужно ли писать атрибут массива. В этом случае они мне не помогают.

1 ответ

Хорошо, я действительно нашел решение для этого, но для этого потребовалась модифицированная версия XmlNodeConverter. Чтобы мои последствия были незначительными, я фактически внес минимальные изменения в фактический код, а затем создал производный класс.

//added this virtual method
protected virtual string GetAttributeValue(string attributeName, JsonReader reader)
{ return reader.Value.ToString();
}
private void ReadElement(JsonReader reader, IXmlDocument document, IXmlNode currentNode, string propertyName, XmlNamespaceManager manager)
{ if (string.IsNullOrEmpty(propertyName)) throw new JsonSerializationException("XmlNodeConverter cannot convert JSON with an empty property name to XML."); Dictionary<string, string=""> attributeNameValues = ReadAttributeElements(reader, manager); string elementPrefix = MiscellaneousUtils.GetPrefix(propertyName); if (propertyName.StartsWith("@")) { var attributeName = propertyName.Substring(1); //Made the change below to use the new method //var attributeValue = reader.Value.ToString(); var attributeValue = GetAttributeValue(attributeName, reader); ...
// Modified to virtual to allow derived class to override. Added attributeName parameter
protected virtual string ConvertTokenToXmlValue(string attributeName, JsonReader reader)
{ if (reader.TokenType == JsonToken.String) { return reader.Value.ToString(); } ....
</string,>

Затем я создал следующий производный конвертер узлов XML.

public class DerivedXmlNodeConverter : Newtonsoft.Json.Converters.XmlNodeConverter
{
private Dictionary<string, string=""> _attributeFormatStrings;
public Dictionary<string, string=""> AttributeFormatStrings
{ get { if (_attributeFormatStrings == null) _attributeFormatStrings = new Dictionary<string,string>(); return _attributeFormatStrings; }
}
protected override string GetAttributeValue(string attributeName, JsonReader reader)
{ Console.WriteLine("getting attribute value: " + attributeName); if (AttributeFormatStrings.ContainsKey(attributeName)) { return string.Format(AttributeFormatStrings[attributeName], reader.Value); } else return base.GetAttributeValue(attributeName, reader);
}
protected override string ConvertTokenToXmlValue(string attributeName, JsonReader reader)
{ if (AttributeFormatStrings.ContainsKey(attributeName)) { return string.Format(AttributeFormatStrings[attributeName], reader.Value); } else return base.ConvertTokenToXmlValue(attributeName, reader);
}
}
</string,string></string,></string,>

Затем мне пришлось реплицировать код, который делает JsonConvert.DeserializeXNode.

DerivedXmlNodeConverter derived = new DerivedXmlNodeConverter(); derived.WriteArrayAttribute = false; derived.DeserializeRootElementName = null; derived.AttributeFormatStrings["*********"] = "{0:0.000}"; JsonSerializerSettings settings = new JsonSerializerSettings { Converters = new JsonConverter[] { derived } }; StringReader sr = new StringReader(test.ToString(Newtonsoft.Json.Formatting.Indented)); JsonReader reader = new JsonTextReader(sr); JsonSerializer ser = JsonSerializer.CreateDefault(settings); ser.CheckAdditionalContent = true; XDocument intoXml = (XDocument)(ser.Deserialize(reader, typeof(XDocument)));

Я думаю, что это были бы большие изменения в Newtownsoft framework-, чтобы позволить этим перехватам для настройки. Надеюсь, этот код поможет всем, кому это нужно.

-David

licensed under cc by-sa 3.0 with attribution.