将Boolean JValue转换为可分析布尔字符串

问题描述:

我有一个Web服务正在解析JSON请求并使用值来设置XML文档的属性。将Boolean JValue转换为可分析布尔字符串

例如,以下请求

{ name: "Foo", isEnabled: true, size: 100 } 

应该更新XML文档此,

<SomeElement name="Foo" isEnabled="true" size="100" /> 

,而是它会产生这样的:

<SomeElement name="Foo" isEnabled="True" size="100" /> 

我没有用于JSON输入或我正在修改的XML的结构化类型(我是这里的中间人),所以我解析了JSON到JObject,XML是原始的XmlDocument

问题是,当我浏览JObject时,我得到每个属性JValue,并通过调用JValue.ToString()将其转换为字符串以放入XML属性。对于整数和字符串值,这工作得很好,但是布尔值,JValue.ToString()导致True/False,而不是true/false所以当XML文档的用户试图将XML文档解析为他们的对象,它失败,因为True是无效的布尔值。另一方面,如果我使用JsonConvert.SerializeObject()来转换值,那么布尔值和整数值将工作,但字符串值将被引用(按照JSON的要求)。

有没有更好的方式来获得正确的弦值,我需要,还是我只是需要特殊的情况下布尔JValue在我的转换代码?

逻辑您需要的是XmlNodeConverter.ConvertTokenToXmlValue(),根据JSON令牌类型调用正确的XmlConvert.ToString()重载。不幸的是,这不是公开的。访问此方法最简单的方法(而不是复制它的逻辑我想)是创建一个临时JObject包含您JValue,它XmlNodeConverter转换为XElement,然后返回创建XElement的价值:

public static class JsonExtensions 
{ 
    public static string ToXmlValue(this JValue value) 
    { 
     if (value == null) 
      return null; 
     var obj = new JObject(new JProperty("a", value.DeepClone())); // XmlNodeConverter only works deserializing an object, so make a synthetic object. 
     return obj.ToXElement().Value; 
    } 

    public static XElement ToXElement(this JObject obj) 
    { 
     if (obj == null) 
      return null; 
     using (var reader = obj.CreateReader()) 
      return JsonExtensions.DeserializeXElement(reader); 
    } 

    public static XElement DeserializeXElement(JsonReader reader) 
    { 
     return DeserializeXElement(reader, null, false); 
    } 

    public static XElement DeserializeXElement(JsonReader reader, string deserializeRootElementName, bool writeArrayAttribute) 
    { 
     var converter = new Newtonsoft.Json.Converters.XmlNodeConverter() { DeserializeRootElementName = deserializeRootElementName, WriteArrayAttribute = writeArrayAttribute }; 
     var jsonSerializer = JsonSerializer.CreateDefault(new JsonSerializerSettings { Converters = new JsonConverter[] { converter } }); 
     return jsonSerializer.Deserialize<XElement>(reader); 
    } 
} 

这应该正确处理所有向XML的值类型转换 - DateTime,bool,decimal等 - 具有正确的国际化。

你也可能想看看Converting between JSON and XML,看看Json.NET内置的转换API可以帮助你。

+0

是的,不幸的是,我不能仅仅使用内置的Json.NET转换,因为它们在丢失订单信息时使用了一些问题。我选择这个作为正确的答案,因为它会返回可用类型的“正确的”序列化值。希望它最终不会太昂贵。 –

您可以为JValue,让结果创建一个扩展方法,你想:

public static class JsonExtensions 
{ 
    public static string ToXmlFriendlyString(this JValue jv) 
    { 
     return (jv.Type == JTokenType.Boolean ? jv.ToString().ToLower() : jv.ToString()); 
    } 
} 

然后,无论你在呼唤JValue.ToString()调用扩展方法来代替,例如:

JValue jv = new JValue(true); 
Console.WriteLine(jv.ToXmlFriendlyString()); 
+0

可能是最有效的选择,但我希望避免特殊情况下的各种类型。 –