-
-
Save randyburden/5924981 to your computer and use it in GitHub Desktop.
using System; | |
using Newtonsoft.Json; | |
namespace JsonConverters | |
{ | |
/// <summary> | |
/// Handles converting JSON string values into a C# boolean data type. | |
/// </summary> | |
public class BooleanJsonConverter : JsonConverter | |
{ | |
#region Overrides of JsonConverter | |
/// <summary> | |
/// Determines whether this instance can convert the specified object type. | |
/// </summary> | |
/// <param name="objectType">Type of the object.</param> | |
/// <returns> | |
/// <c>true</c> if this instance can convert the specified object type; otherwise, <c>false</c>. | |
/// </returns> | |
public override bool CanConvert( Type objectType ) | |
{ | |
// Handle only boolean types. | |
return objectType == typeof( bool ); | |
} | |
/// <summary> | |
/// Reads the JSON representation of the object. | |
/// </summary> | |
/// <param name="reader">The <see cref="T:Newtonsoft.Json.JsonReader"/> to read from.</param> | |
/// <param name="objectType">Type of the object.</param> | |
/// <param name="existingValue">The existing value of object being read.</param> | |
/// <param name="serializer">The calling serializer.</param> | |
/// <returns> | |
/// The object value. | |
/// </returns> | |
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 ); | |
} | |
/// <summary> | |
/// Specifies that this converter will not participate in writing results. | |
/// </summary> | |
public override bool CanWrite { get { return false; } } | |
/// <summary> | |
/// Writes the JSON representation of the object. | |
/// </summary> | |
/// <param name="writer">The <see cref="T:Newtonsoft.Json.JsonWriter"/> to write to.</param><param name="value">The value.</param><param name="serializer">The calling serializer.</param> | |
public override void WriteJson( JsonWriter writer, object value, JsonSerializer serializer ) | |
{ | |
} | |
#endregion Overrides of JsonConverter | |
} | |
} |
nice, thanks.
Has anyone actually tested this implementation, including the author? I doubt it, because it does not work.
If you try this:
namespace ConsoleApp1
{
public class BooleanJsonConverter {...}
class Program
{
static void Main(string[] args)
{
Console.WriteLine($"\"true\" -> {JsonConvert.DeserializeObject<bool>("true")}");
try
{
Console.WriteLine($"\"yes\" -> {JsonConvert.DeserializeObject<bool>("yes", new BooleanJsonConverter())}");
}
catch (Exception e)
{
Console.WriteLine($"Exception: {e}");
}
}
}
You will get this:
"true" -> True
Exception: Newtonsoft.Json.JsonReaderException: Unexpected character encountered while parsing value: y. Path '', line 0, position 0.
at Newtonsoft.Json.JsonTextReader.ParseValue()
at Newtonsoft.Json.JsonTextReader.Read()
at Newtonsoft.Json.JsonReader.ReadForType(JsonContract contract, Boolean hasConverter)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize(JsonReader reader, Type objectType, Boolean checkAdditionalContent)
at Newtonsoft.Json.JsonSerializer.DeserializeInternal(JsonReader reader, Type objectType)
at Newtonsoft.Json.JsonConvert.DeserializeObject(String value, Type type, JsonSerializerSettings settings)
at Newtonsoft.Json.JsonConvert.DeserializeObject(String value, Type type, JsonConverter[] converters)
at Newtonsoft.Json.JsonConvert.DeserializeObject[T](String value, JsonConverter[] converters)
at ConsoleApp1.Program.Main(String[] args) in C:\Users\ryanj\PersonalDev\ConsoleApp1\ConsoleApp1\Program.cs:line 247
which is exactly the same failure mode as described by this SO post, for which this very Gist was proposed as a solution.
I tested and it works for me like this.
class Program
{
static void Main(string[] args)
{
Console.WriteLine($"\"true\" -> {JsonConvert.DeserializeObject<bool>("true")}");
try
{
//Console.WriteLine($"\"yes\" -> {JsonConvert.DeserializeObject<bool>("yes", new BooleanConverter())}");
Console.WriteLine($"\"yes\" -> {JsonConvert.DeserializeObject<MyClass>("{IsValid: 'no'}", new BooleanJsonConverter())}");
}
catch (Exception e)
{
Console.WriteLine($"Exception: {e}");
}
}
And My Class is :
public class MyClass
{
public bool IsValid { get; set; }
public override string ToString()
{
return IsValid.ToString();
}
}
It's really nice way to resolve booleans. Just addon for nullable booleans
public override bool CanConvert(Type objectType)
{
if (Nullable.GetUnderlyingType(objectType) != null)
{
return Nullable.GetUnderlyingType(objectType) == typeof(bool);
}
return objectType == typeof(bool);
}
If you try this:
namespace ConsoleApp1 { public class BooleanJsonConverter {...} class Program { static void Main(string[] args) { Console.WriteLine($"\"true\" -> {JsonConvert.DeserializeObject<bool>("true")}"); try { Console.WriteLine($"\"yes\" -> {JsonConvert.DeserializeObject<bool>("yes", new BooleanJsonConverter())}"); } catch (Exception e) { Console.WriteLine($"Exception: {e}"); } } }You will get this:
"true" -> True Exception: Newtonsoft.Json.JsonReaderException: Unexpected character encountered while parsing value: y. Path '', line 0, position 0. at Newtonsoft.Json.JsonTextReader.ParseValue() at Newtonsoft.Json.JsonTextReader.Read() at Newtonsoft.Json.JsonReader.ReadForType(JsonContract contract, Boolean hasConverter) at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize(JsonReader reader, Type objectType, Boolean checkAdditionalContent) at Newtonsoft.Json.JsonSerializer.DeserializeInternal(JsonReader reader, Type objectType) at Newtonsoft.Json.JsonConvert.DeserializeObject(String value, Type type, JsonSerializerSettings settings) at Newtonsoft.Json.JsonConvert.DeserializeObject(String value, Type type, JsonConverter[] converters) at Newtonsoft.Json.JsonConvert.DeserializeObject[T](String value, JsonConverter[] converters) at ConsoleApp1.Program.Main(String[] args) in C:\Users\ryanj\PersonalDev\ConsoleApp1\ConsoleApp1\Program.cs:line 247which is exactly the same failure mode as described by this SO post, for which this very Gist was proposed as a solution.
You are trying t o deserialize the input yes
into a bool
. This is not a valid JSON string. Try it with "yes"
instead:
bool yes = JsonConvert.DeserializeObject<bool>("\"yes\"", new BooleanJsonConverter())
It worked for me in my case and as I implemented it in a .net 6 service I added it to program.cs so that it would work for all requests. Thank you very much for sharing this.
var builder = WebApplication.CreateBuilder(args); builder.Services.AddControllers().AddNewtonsoftJson(options => { options.SerializerSettings.Converters.Add(new BooleanJsonConverter()); });
I was just about to implement this when I spotted yours. Thanks!