如何让newtonsoft反序列化yes和no布尔(how to get newtonsoft to

2019-07-18 17:13发布

注:我已经提供了这个饲料底部的解决方案。

我有一个C#赢8应用程序在那里我反序列化JSON一些看起来像这样:

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

到使用此接口的类:

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

但是Newtonsoft抛出一个错误:

在解析值意外字符遇到:N。 路径“单元[0] .isAvailable,线1,位置42。

有没有一种方法来扩展是/否或1/0基于得到的对象属性bool类型的Newtonsoft解析? 现在它仅适用于真/假。

有自定义转换器的几个职位的类别,而不是原始类型像布尔。

有什么建议?

Answer 1:

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; }
}


Answer 2:

我建议这种方法

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 )
        {
        }

    }
}


Answer 3:

//这是我想出了...

   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<IUnit> 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<JToken>(reader) as JObject;

            if (obj != null)
            {
                string result = obj["isSingleUnit"].ToObject<string>();

                bool isSingleUnit = ConvertToBool(result);

                string name = obj["name"].ToObject<string>();

                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();
    }
}
}


Answer 4:

这是我想出了。

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<T>(json, new JsonBooleanConverter());


Answer 5:

下面是任何人的一个版本@约翰在VB中的解决方案,需要一个。 它处理布尔和null的布尔值。 在写它转换成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


文章来源: how to get newtonsoft to deserialize yes and no to boolean