Json.NET,可以将SerializeXmlNode扩展为检测数字吗?

时间:2014-03-31 19:49:18

标签: c# json.net

我正在使用SerializeXmlNode从XML转换为JSON。看起来预期的行为是将所有XML值转换为字符串,但我想在适当的时候发出真正的数值。

// Input:   <Type>1</Type>
string json = JsonConvert.SerializeXmlNode(node, Newtonsoft.Json.Formatting.Indented, true);
// Output:  "Type": "1"
// Desired: "Type": 1

我是否需要编写自定义转换器才能执行此操作,或者是否可以通过代理方式在适当的位置挂钩序列化过程?或者,我必须编写自己的自定义JsonConverter类来管理转换吗?

Regex Hack

鉴于适当解决方案的复杂性,这是另一个(我并不完全为此感到自豪,但它有效......)。

// Convert to JSON, and remove quotes around numbers
string json = JsonConvert.SerializeXmlNode(node, Newtonsoft.Json.Formatting.Indented, true);

// HACK to force integers as numbers, not strings.
Regex rgx = new Regex("\"(\\d+)\"");
json = rgx.Replace(json, "$1");

1 个答案:

答案 0 :(得分:3)

XML没有办法区分像JSON那样的基本类型。因此,在将XML直接转换为JSON时,Json.Net不知道值应该是什么类型,而不是猜测。如果它总是假设仅由数字组成的值是序数,那么诸如邮政编码和带有前导零的电话号码之类的东西将在转换中被破坏。因此,Json.Net采取安全的道路并将所有值视为字符串并不奇怪。

解决此问题的一种方法是将XML反序列化为中间对象,然后将其序列化为JSON。由于中间对象具有强类型属性,Json.Net知道输出什么。这是一个例子:

class Program
{
    static void Main(string[] args)
    {
        string xml = @"<root><ordinal>1</ordinal><postal>02345</postal></root>";

        XmlSerializer xs = new XmlSerializer(typeof(Intermediary));
        using (TextReader reader = new StringReader(xml))
        {
            Intermediary obj = (Intermediary)xs.Deserialize(reader);
            string json = JsonConvert.SerializeObject(obj , Formatting.Indented);
            Console.WriteLine(json);
        }
    }
}

[XmlRoot("root")]
public class Intermediary
{
    public int ordinal { get; set; }
    public string postal { get; set; }
}

以上输出:

{
  "ordinal": 1,
  "postal": "02345"
}

要制作更通用的解决方案,是的,您必须编写自己的转换器。实际上,使用Json.Net附带的SerializeXmlNode完成调用XmlNodeConverter时发生的XML到JSON转换。此转换器本身似乎不是非常可扩展的,但您始终可以使用其source code作为创建自己的转换点。