I am using C#
to deserialize a collection of JSON strings. Each string has a property employer_normalized
that is supposed to contain a string
and List<int>
where the values in the List
are always positive. In some cases employer_normalized
is set to -1
, so I want to override these cases with some behavior that sets employer_normalized
to null
.
Here is my class:
public class EmployerNormalized
{
public string company;
public List<int> code;
}
Good JSON
"employer_normalized": {
"company": "self",
"code": [
"4581 ",
"6732 ",
"9121",
"9999 ",
"5947 ",
"8322 ",
"8351 ",
"7335 ",
"9999 ",
"4225 ",
"8399 "
]
}
Bad JSON
"employer_normalized": -1
I am currently using Json.NET
to do my JSON parsing. What is an elegant solution to solving this problem? Is it best to just set the employer_normalized
value to null
if it is -1
? If so, how can I do this?
You can use a custom JsonConverter to deal with this situation. Wherever you are expecting a EmployerNormalized
, the converter can check whether the value of that property is -1
and return null, otherwise deserialize it normally.
Here is the code for the converter:
public class EmployerNormalizedConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return (objectType == typeof(EmployerNormalized));
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
JToken token = JToken.Load(reader);
if (token.Type == JTokenType.Object)
{
return token.ToObject<EmployerNormalized>();
}
return null;
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
And here is a demo showing how to use it:
class Program
{
static void Main(string[] args)
{
string json = @"
{
""good"" : {
""company"": ""self"",
""code"": [
""4581 "",
""6732 "",
""9121"",
""9999 "",
""5947 "",
""8322 "",
""8351 "",
""7335 "",
""9999 "",
""4225 "",
""8399 ""
]
},
""bad"" : -1
}";
Wrapper wrapper =
JsonConvert.DeserializeObject<Wrapper>(json,
new EmployerNormalizedConverter());
DumpEmployer("good", wrapper.good);
DumpEmployer("bad", wrapper.bad);
}
private static void DumpEmployer(string prop, EmployerNormalized emp)
{
Console.WriteLine(prop);
if (emp != null)
{
Console.WriteLine(" company: " + emp.company);
Console.WriteLine(" codes: " +
string.Join(", ", emp.code.Select(c => c.ToString())));
}
else
Console.WriteLine(" (null)");
}
public class Wrapper
{
public EmployerNormalized good { get; set; }
public EmployerNormalized bad { get; set; }
}
public class EmployerNormalized
{
public string company;
public List<int> code;
}
}
Here is the output:
good
company: self
codes: 4581, 6732, 9121, 9999, 5947, 8322, 8351, 7335, 9999, 4225, 8399
bad
(null)
Important note: You might be tempted to decorate the EmployerNormalized
class with [JsonConverter(typeof(EmployerNormalizedConverter))]
, but if you do that, then the converter, in its current form, will end up calling itself recursively until it errors out with a StackOverflowException
. If you need/want to use the attribute, then the code of the ReadJson
method in the converter will need to be changed so that it manually creates an instance of the EmployerNormalized
class and populates all of its properties individually rather than calling token.ToObject<EmployerNormalized>()
. Here is an alternate version of ReadJson
that will avoid the recursion problem:
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
JToken token = JToken.Load(reader);
if (token.Type == JTokenType.Object)
{
EmployerNormalized employer = new EmployerNormalized();
employer.company = token["company"].ToString();
employer.code = token["code"].ToObject<List<int>>();
return employer;
}
return null;
}
I know this sucks, but you can first try to parse the JSON string
to an Object
with the structure of your Good JSON, and in case of parsing error, parse to the second case (Bad JSON).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With