-
-
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 | |
| } | |
| } |
Thanks for sharing !
I was just about to implement this when I spotted yours. Thanks!
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 247which 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()); });
thanks a lot for sharing