如何让newtonsoft反序列化yes和no to boolean

注意:我已在此Feed的底部提供了解决方案。

我有一个C#Win 8应用程序,我正在对一些看起来像这样的json进行反序列化:

{ 'Unit': [ { 'name':'House 123', isAvailable:'no' }, { 'name':'House 456', isAvailable:'yes' }] } 

进入使用此接口的类:

 public interface IUnit { string Name { get; } bool isAvailable { get; } } 

但是牛顿软件引发了一个错误:

解析值时遇到意外的字符:n。 路径’单位[0] .isAvailable,第1行,第42位。

有没有办法根据生成的对象属性类型bool扩展Newtonsoft来解析yes / no或1/0? 现在它只适用于真/假。

类的自定义转换器上有几个post,但不是像bool这样的原始类型。

有什么建议?

 public class MyBooleanConverter : JsonConverter { public override bool CanWrite { get { return false; } } public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { throw new NotImplementedException(); } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { var value = reader.Value; if (value == null || String.IsNullOrWhiteSpace(value.ToString())) { return false; } if ("yes".Equals(value, StringComparison.OrdinalIgnoreCase)) { return true; } return false; } public override bool CanConvert(Type objectType) { if (objectType == typeof(String) || objectType == typeof(Boolean)) { return true; } return false; } } public interface IUnit { string Name { get; } [JsonConverter(typeof(MyBooleanConverter))] bool isAvailable { get; } } 

我会建议这种方法

 using System; using Newtonsoft.Json; namespace JsonConverters { public class BooleanJsonConverter : JsonConverter { public override bool CanConvert( Type objectType ) { return objectType == typeof( bool ); } public override object ReadJson( JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer ) { switch ( reader.Value.ToString().ToLower().Trim() ) { case "true": case "yes": case "y": case "1": return true; case "false": case "no": case "n": case "0": return false; } // If we reach here, we're pretty much going to throw an error so let's let Json.NET throw it's pretty-fied error message. return new JsonSerializer().Deserialize( reader, objectType ); } public override void WriteJson( JsonWriter writer, object value, JsonSerializer serializer ) { } } } 

//这就是我想出来的……

  using System; using System.Collections.Generic; using System.IO; using System.Linq; using Newtonsoft.Json; using Newtonsoft.Json.Linq; namespace NewtonTest { internal class NewtonTest { public class Data { public IEnumerable Unit { get; set; } public override string ToString() { return string.Format("Data{{Unit=[{0}]}}", string.Join(", ", Unit.Select(c => string.Format("{0} - Single Unit: {1}", c.Name, c.isSingleUnit.ToString())))); } } public interface IUnit { string Name { get; } // [JsonConverter(typeof(Converter))] bool isSingleUnit { get; } } public class House : IUnit { public House(string name, bool isSingle) { this.Name = name; this.isSingleUnit = isSingle; } public string Name { get; private set; } public bool isSingleUnit { get; private set; } } public class Apartment : IUnit { public Apartment(string name, bool isSingle) { this.Name = name; this.isSingleUnit = isSingle; } public string Name { get; private set; } public bool isSingleUnit { get; private set; } } private static bool ConvertToBool(string value) { value = value.ToUpper(). Replace("YES", "TRUE"). Replace("Y", "TRUE"). Replace("1", "TRUE"). Replace("NO", "FALSE"). Replace("N", "FALSE"). Replace("0", "FALSE"); bool result = false; bool.TryParse(value, out result); return result; } private class UnitConverter : Newtonsoft.Json.JsonConverter { public override bool CanConvert(Type objectType) { return typeof (NewtonTest.IUnit).IsAssignableFrom(objectType); } public override object ReadJson(Newtonsoft.Json.JsonReader reader, Type objectType, object existingValue, Newtonsoft.Json.JsonSerializer serializer) { JObject obj = serializer.Deserialize(reader) as JObject; if (obj != null) { string result = obj["isSingleUnit"].ToObject(); bool isSingleUnit = ConvertToBool(result); string name = obj["name"].ToObject(); if (isSingleUnit) { return new NewtonTest.House(name, isSingleUnit); } else { return new NewtonTest.Apartment(name, isSingleUnit); } } else { return null; } } public override void WriteJson(Newtonsoft.Json.JsonWriter writer, object value, Newtonsoft.Json.JsonSerializer serializer) { throw new NotImplementedException(); } } public static void Main() { Newtonsoft.Json.JsonSerializer serializer = new Newtonsoft.Json.JsonSerializer(); serializer.Converters.Add(new UnitConverter()); string json = "{'Unit':[{'name':'Apartment 123',isSingleUnit:'no'},{'name':'House 456',isSingleUnit:'yes'}]}".Replace( '\'', '\"'); var obj = serializer.Deserialize(new StringReader(json), typeof (Data)); Console.WriteLine(obj); Console.ReadKey(); } } } 

这就是我提出的。

 public class JsonBooleanConverter : JsonConverter { public override bool CanWrite { get { return false; } } public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { throw new NotImplementedException(); } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { var value = reader.Value.ToString().ToLower().Trim(); switch (value) { case "true": case "yes": case "y": case "1": return true; } return false; } public override bool CanConvert(Type objectType) { if (objectType == typeof(Boolean)) { return true; } return false; } } 

用法:

 var myObj = JsonConvert.DeserializeObject(json, new JsonBooleanConverter()); 

这是@ vb在vb中的解决方案,适用于任何需要它的人。 它处理布尔值和可空值布尔值。 在写入它转换为0/1以保存传输中的一些字节(而不是真/假):

 Imports Newtonsoft.Json Public Class MyBooleanConverter Inherits JsonConverter Public Overrides ReadOnly Property CanWrite As Boolean Get Return True End Get End Property Public Overrides Sub WriteJson(writer As JsonWriter, value As Object, serializer As JsonSerializer) Dim boolVal As Boolean = value writer.WriteValue(If(boolVal, 1, 0)) End Sub Public Overrides Function ReadJson(reader As JsonReader, objectType As Type, existingValue As Object, serializer As JsonSerializer) As Object Dim value = reader.Value If IsNothing(value) OrElse String.IsNullOrWhiteSpace(value.ToString()) OrElse "0" = value Then Return False End If If 0 = String.Compare("yes", value, True) OrElse 0 = String.Compare("true", value, True) Then Return True End If Return False End Function Public Overrides Function CanConvert(objectType As Type) As Boolean Return objectType = GetType(Boolean) OrElse objectType = GetType(Boolean?) 'OrElse objectType = GetType(String) End Function End Class