简体   繁体   中英

intercept JSON in C# to return a list of nullable boolean

I am getting an error when I try to return a list of nullable boolean from my JSON interceptor. The interceptor attribute is:

[JsonConverter(typeof(NullableBoolListDeSerializer))]
public List<bool?> ExemptBenefits { get; set; }

The ReadJSON method on the interceptor is:

 List<bool?> result = new List<bool?>();

        (reader as Newtonsoft.Json.Linq.JTokenReader).CurrentToken.ToList().ForEach(item =>
        {
            string value = (String)item.ToObject(typeof(String));
            switch (value.ToLower())
            {
                case "true":
                case "yes":
                case "1":
                    result.Add(true);
                    break;
                case "false":
                case "no":
                case "0":
                default:
                    result.Add(false);
                    break;
            }
        });
        return result;

The JSON being submitted is:

{
  "exemptBenefits": [
     "1"
  ],
  "_apiEndpoint": "/benefits/loan"
}

The error I am getting is:

Unexpected token when deserializing object: String. Path 'exemptBenefits[0]', line 1, position 187.

Wondering how to convert a list of strings (eg "1","0"."true", "false") from JSON to a List (true,false,true,false) in a JSON interceptor (actually it is NewtonSoft.Json)

If you want to convert a list of string values into a list of nullable boolean values with a JsonConverter class, I would recommend using a JArray inside the converter instead of trying to deal with the reader directly. This will allow you to simplify your code while also avoiding the error you encountered:

class NullableBoolListDeSerializer : JsonConverter
{
    readonly string[] TrueStrings = { "true", "yes", "1" };

    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(List<bool?>);
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        return JArray.Load(reader)
            .Children<JValue>()
            .Select(jv =>
            {
                string b = (string)jv;
                return b != null ? TrueStrings.Contains(b.ToLower()) : (bool?)null;
            })
            .ToList();
    }

    public override bool CanWrite
    {
        get { return false; }
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}

Fiddle: https://dotnetfiddle.net/JaP5W7

Of course, you can actually do better than that. Instead of making your converter handle a List<bool?> , make it handle just a simple bool? instead, eg:

class NullableBoolDeSerializer : JsonConverter
{
    readonly string[] TrueStrings = { "true", "yes", "1" };

    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(bool?);
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        string b = (string)reader.Value;
        return b != null ? TrueStrings.Contains(b.ToLower()) : (bool?)null;
    }

    public override bool CanWrite
    {
        get { return false; }
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}

Then, swap out the [JsonConverter] attribute on your ExemptBenefits property declaration for a [JsonProperty] attribute that has its ItemConverterType parameter set to the simplified converter. Json.Net will then handle creating the list for you.

[JsonProperty(ItemConverterType = typeof(NullableBoolDeSerializer))]
public List<bool?> ExemptBenefits { get; set; }

Fiddle: https://dotnetfiddle.net/Dp4N11

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM