Empty string is treated as null
See original GitHub issueSource/destination types
namespace QuickType
{
using System;
using System.Collections.Generic;
using System.Globalization;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
public partial class TopLevel
{
[JsonProperty("bar", Required = Required.DisallowNull, NullValueHandling = NullValueHandling.Ignore)]
public Bar? Bar { get; set; }
}
public enum Bar { Foo, Empty };
public partial class TopLevel
{
public static TopLevel FromJson(string json) => JsonConvert.DeserializeObject<TopLevel>(json, QuickType.Converter.Settings);
}
static class BarExtensions
{
public static Bar? ValueForString(string str)
{
Console.WriteLine("value for string");
switch (str)
{
case "": Console.WriteLine("empty"); return Bar.Empty;
case "foo": return Bar.Foo;
default: return null;
}
}
public static Bar ReadJson(JsonReader reader, JsonSerializer serializer)
{
var str = serializer.Deserialize<string>(reader);
var maybeValue = ValueForString(str);
if (maybeValue.HasValue) return maybeValue.Value;
throw new Exception("Unknown enum case " + str);
}
public static void WriteJson(this Bar value, JsonWriter writer, JsonSerializer serializer)
{
switch (value)
{
case Bar.Empty: serializer.Serialize(writer, ""); break;
case Bar.Foo: serializer.Serialize(writer, "foo"); break;
}
}
}
public static class Serialize
{
public static string ToJson(this TopLevel self) => JsonConvert.SerializeObject(self, QuickType.Converter.Settings);
}
internal class Converter: JsonConverter
{
public override bool CanConvert(Type t) => t == typeof(Bar) || t == typeof(Bar?);
public override object ReadJson(JsonReader reader, Type t, object existingValue, JsonSerializer serializer)
{
if (t == typeof(Bar))
return BarExtensions.ReadJson(reader, serializer);
if (t == typeof(Bar?))
{
if (reader.TokenType == JsonToken.Null) return null;
return BarExtensions.ReadJson(reader, serializer);
}
throw new Exception("Unknown type");
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
var t = value.GetType();
if (t == typeof(Bar))
{
((Bar)value).WriteJson(writer, serializer);
return;
}
throw new Exception("Unknown type");
}
public static readonly JsonSerializerSettings Settings = new JsonSerializerSettings
{
MetadataPropertyHandling = MetadataPropertyHandling.Ignore,
DateParseHandling = DateParseHandling.None,
Converters = {
new Converter()
}
};
}
class Program
{
static void Main(string[] args)
{
var path = args[0];
var json = System.IO.File.ReadAllText(path);
var data = TopLevel.FromJson(json);
Console.WriteLine("have data");
var output = data.ToJson();
Console.WriteLine("{0}", output);
}
}
}
Source/destination JSON
{
"bar": ""
}
Expected behavior
value for string
empty
have data
{"bar":""}
Actual behavior
value for string
empty
Unhandled Exception: Newtonsoft.Json.JsonSerializationException: Required property 'bar' expects a non-null value. Path '', line 3, position 1.
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.EndProcessProperty(Object newObject, JsonReader reader, JsonObjectContract contract, Int32 initialDepth, JsonProperty property, PropertyPresence presence, Boolean setDefaultValue)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.PopulateObject(Object newObject, JsonReader reader, JsonObjectContract contract, JsonProperty member, String id)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
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[T](String value, JsonSerializerSettings settings)
at QuickType.TopLevel.FromJson(String json) in /private/tmp/csharp-071760/Program.cs:line 20
at QuickType.Program.Main(String[] args) in /private/tmp/csharp-071760/Program.cs:line 102
Remarks
It works for {"bar":"foo"}
, so the problem seems to be that the string is empty.
Issue Analytics
- State:
- Created 5 years ago
- Reactions:1
- Comments:12
Top Results From Across the Web
Difference between null and empty string [duplicate]
Null means nothing. Its just a literal. Null is the value of reference variable. But empty string is blank.It gives the length=0 ....
Read more >When to Use NULL and When to Use Empty String
A string refers to a character's sequence. Sometimes strings can be empty or NULL. The difference is that NULL is used to refer...
Read more >When to use NULL and when to use an empty string?
NULL means absence of value (i.e. there is no value), while empty string means there is a string value of zero length. For...
Read more >Understanding Null Versus the Empty String
The value null represents the absence of any object, while the empty string is an object of type String with zero characters. If...
Read more >Empty String Considered Harmful - Sam Jarman
The use of empty strings when used to indicate a null value or lack of value, when the language you're using has a...
Read more >
Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free
Top Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Is there any reason this couldn’t be settable in the
JsonSerializerSettings
?This is creating a problem for my integration. In the Database we have a field that doesn’t support NULL, and I just noticed the end users are adding empty strings there. When I’m transferring this data to another database, using a service that converts this data into JSON, I got failures on the target table because the column doesn’t accept NULL.
I was thinking that if I have a JSON with a empty string when I deserialize I should get the same value, an empty string.
This looks like a bug on the implementation to me and not in the specification as mentioned before.