当尝试将具有空属性名的JSON转换为XML时,会出现异常

时间:2023-01-12 21:53:47

I've got a service that takes various file formats from my clients and converts them to XML to be processed by an internal processing engine. For JSON I'm using Json.Net's JsonConvert.DeserializeXmlNode to convert the JSON to XML. Today I've run into an issue where a client is sending JSON that contains a property with an empty name, which apparently is a valid scenario. When I try to convert to XML I get the exception below. What I'm trying to figure out is the best way to tell the XmlNodeConverter that I want it to either skip or give a default name to an element when this happens. Is that possible?

我有一个服务,它从我的客户端获取各种文件格式,并将它们转换为XML,由内部处理引擎进行处理。对于JSON,我使用的是JSON。净的JsonConvert。DeserializeXmlNode将JSON转换为XML。今天我遇到了一个问题,客户机正在发送JSON,其中包含一个空名称的属性,这显然是一个有效的场景。当我试图转换为XML时,我得到了下面的异常。我想弄明白的是,告诉XmlNodeConverter,我希望它在发生这种情况时跳过或给元素一个默认名称。这有可能吗?

Any advice would be greatly appreciated! Thanks!

如有任何建议,我们将不胜感激!谢谢!

Sample Unit Test:

样本单元测试:

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

    XmlDocument xdoc = JsonConvert.DeserializeXmlNode( json );
}

The exception I'm getting is:

我得到的例外是:

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 个解决方案

#1


1  

XmlNodeConverter does not seem to provide any public options to change how it handles empty JSON property names. I would have suggested subclassing the converter, but most of its internal methods are private, so that pretty much kills that idea.

XmlNodeConverter似乎没有提供任何公共选项来更改如何处理空JSON属性名。我可能会建议对转换器进行子类化,但是它的大多数内部方法都是私有的,所以这几乎扼杀了这个想法。

It looks like your best option is to pre-process the JSON to replace the empty property names with some other value. You can use Json.Net's LINQ-to-JSON API to do this, then send the corrected JSON to JsonConvert.DeserializeXmlNode as you were before. I would create a small helper class like this:

看起来您最好的选择是预先处理JSON,用其他值替换空属性名。您可以使用Json。Net的LINQ-to-JSON API可以做到这一点,然后将正确的JSON发送到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);
            }
        }
    }
}

Then, in your code, just replace JsonConvert.DeserializeXmlNode() with JsonHelper.ConvertToXml():

然后,在代码中,只需将JsonConvert.DeserializeXmlNode()替换为JsonHelper.ConvertToXml():

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

    XmlDocument xdoc = JsonHelper.ConvertToXml( json );
}

Fiddle: https://dotnetfiddle.net/ahvytn

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

#1


1  

XmlNodeConverter does not seem to provide any public options to change how it handles empty JSON property names. I would have suggested subclassing the converter, but most of its internal methods are private, so that pretty much kills that idea.

XmlNodeConverter似乎没有提供任何公共选项来更改如何处理空JSON属性名。我可能会建议对转换器进行子类化,但是它的大多数内部方法都是私有的,所以这几乎扼杀了这个想法。

It looks like your best option is to pre-process the JSON to replace the empty property names with some other value. You can use Json.Net's LINQ-to-JSON API to do this, then send the corrected JSON to JsonConvert.DeserializeXmlNode as you were before. I would create a small helper class like this:

看起来您最好的选择是预先处理JSON,用其他值替换空属性名。您可以使用Json。Net的LINQ-to-JSON API可以做到这一点,然后将正确的JSON发送到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);
            }
        }
    }
}

Then, in your code, just replace JsonConvert.DeserializeXmlNode() with JsonHelper.ConvertToXml():

然后,在代码中,只需将JsonConvert.DeserializeXmlNode()替换为JsonHelper.ConvertToXml():

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

    XmlDocument xdoc = JsonHelper.ConvertToXml( json );
}

Fiddle: https://dotnetfiddle.net/ahvytn

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