尝试将具有空属性名称的JSON转换为XML时获取异常

时间:2017-06-30 12:48:31

标签: c# json xml json.net

我有一个服务,它从我的客户端获取各种文件格式,并将它们转换为XML,由内部处理引擎处理。对于JSON,我使用Json.Net的 JsonConvert.DeserializeXmlNode 将JSON转换为XML。今天我遇到了一个问题,客户端发送的JSON包含一个空名称的属性,这显然是一个有效的场景。当我尝试转换为XML时,我得到以下例外。我想要弄清楚的是告诉XmlNodeConverter我希望它跳过这个元素的最佳方法,或者在发生这种情况时给元素一个默认名称。这可能吗?

任何建议都将不胜感激!谢谢!

样本单元测试:

[Test]
public void TestParseEmptyName( )
{
    string json = @"
    {
        ""Row"":{
            """":123
        }
    }";

    XmlDocument xdoc = JsonConvert.DeserializeXmlNode( json );
}

我得到的例外是:

Newtonsoft.Json.JsonSerializationException occurred
  HResult=0x80131500
  Message=XmlNodeConverter cannot convert JSON with an empty property name to XML. Path 'Row.', line 1, position 14.
  Source=Newtonsoft.Json
  StackTrace:
   at Newtonsoft.Json.Converters.XmlNodeConverter.ReadElement(JsonReader reader, IXmlDocument document, IXmlNode currentNode, String propertyName, XmlNamespaceManager manager)
   at Newtonsoft.Json.Converters.XmlNodeConverter.DeserializeNode(JsonReader reader, IXmlDocument document, XmlNamespaceManager manager, IXmlNode currentNode)
   at Newtonsoft.Json.Converters.XmlNodeConverter.CreateElement(JsonReader reader, IXmlDocument document, IXmlNode currentNode, String elementName, XmlNamespaceManager manager, String elementPrefix, Dictionary`2 attributeNameValues)
   at Newtonsoft.Json.Converters.XmlNodeConverter.ReadElement(JsonReader reader, IXmlDocument document, IXmlNode currentNode, String propertyName, XmlNamespaceManager manager)
   at Newtonsoft.Json.Converters.XmlNodeConverter.DeserializeNode(JsonReader reader, IXmlDocument document, XmlNamespaceManager manager, IXmlNode currentNode)
   at Newtonsoft.Json.Converters.XmlNodeConverter.ReadJson(JsonReader reader, Type objectType, Object existingValue, JsonSerializer serializer)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.DeserializeConvertable(JsonConverter converter, JsonReader reader, Type objectType, Object existingValue)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize(JsonReader reader, Type objectType, Boolean checkAdditionalContent)
   at Newtonsoft.Json.JsonSerializer.DeserializeInternal(JsonReader reader, Type objectType)
   at Newtonsoft.Json.JsonConvert.DeserializeObject(String value, Type type, JsonSerializerSettings settings)
   at Newtonsoft.Json.JsonConvert.DeserializeXmlNode(String value, String deserializeRootElementName, Boolean writeArrayAttribute)
   at Newtonsoft.Json.JsonConvert.DeserializeXmlNode(String value)
   at BMS.Common.Test.Text.JSONParserFixture.TestParseEmptyName() in C:\SVNRepository\BMSProducts\LoanTradeDesk\trunk\Source Code\Common\BMS.Common.Test\Text\JSONParserFixture.cs:line 33

1 个答案:

答案 0 :(得分:1)

{ System.out.println("Enter a number: " ); int number = scan.nextInt(); int [] integerArray = new int[number]; for (int i=0; i < number; i++) { integerArray[i] = (int)(Math.random()); } System.out.println(Arrays.toString(integerArray)); } 似乎没有提供任何公共选项来更改它处理空JSON属性名称的方式。我会建议对转换器进行子类化,但是它的大多数内部方法都是私有的,所以这几乎会杀死这个想法。

看起来您最好的选择是预处理JSON以使用其他值替换空属性名称。您可以使用Json.Net的LINQ-to-JSON API执行此操作,然后将更正的JSON发送到XmlNodeConverter,就像之前一样。我会创建一个这样的小助手类:

JsonConvert.DeserializeXmlNode

然后,在您的代码中,只需将public class JsonHelper { public static XmlDocument ConvertToXml(string json) { JToken token = JToken.Parse(json); // Change "blank" to whatever you want the replacement name to be. ReplaceEmptyPropertyNames(token, "blank"); return JsonConvert.DeserializeXmlNode(token.ToString()); } public static void ReplaceEmptyPropertyNames(JToken token, string replaceWithName) { if (token.Type == JTokenType.Object) { foreach (JProperty prop in token.Children<JProperty>().ToList()) { if (prop.Name == string.Empty) { prop.AddAfterSelf(new JProperty(replaceWithName, prop.Value)); prop.Remove(); } ReplaceEmptyPropertyNames(prop.Value, replaceWithName); } } else if (token.Type == JTokenType.Array) { foreach (JToken child in token.Children()) { ReplaceEmptyPropertyNames(child, replaceWithName); } } } } 替换为JsonConvert.DeserializeXmlNode()

JsonHelper.ConvertToXml()

小提琴:https://dotnetfiddle.net/ahvytn