I’m accessing an api that for some reason returns false
whenever null
would be used normally.
I now need a way to deserialize an arbitrary json string into a completely generic type and interpreting JsonTokenType.False
as JsonTokenType.Null
for any Nullable / reference type property no matter how deep it’s nested.
(I’m targeting net7.0
and netstandard2.0
and use System.Text.Json
)
Example data (Needs to work for ANY schema!)
{
"property": false // expected type: string
"property2": false // expected type: int
"property3": { // data might be nested
"property": false // expected type SomeType
}
}
public sealed class JsonDefinition {
public string? Property { get; set; }
public int? Property2 { get; set; }
public NestedJsonType? Property { get; set; }
}
public sealed class NestedJsonType{
public SomeType? Property { get; set; }
}
3
Answers
I guess I'll just go with sth like
input.Replace("false", "null")
for now...System.Text.Json is only good for a demo to serialize "Hello World". I tried to use it , but code is getting unnecessary complicated. So I give you a Newtonsoft.Json converter. If you are a fan of Text.Json try to convert to it and you will see what I am talking about
If you are using .NET 7 (or the System.Text.Json nuget version 7) or later, you can add a
DefaultJsonTypeInfoResolver
modifier that applies a "false as default" converter to every property of every type encountered during deserialization:First, create the following
Action<JsonTypeInfo>
modifier:And now you will be able to deserialize your JSON as follows:
Notes:
Because the converter is applied directly to each serialized property, there is no problem with recursion.
This solution does not handle
false
values for the root object, or for collection items.You may need to tweak the
// TODO: Modify these checks as required.
logic that selects the property types to which to apply the converter.Demo fiddle #1 here.
If you are using .NET 6 then contract customization is not available. Instead, you could preload into a
JsonNode
hierarchy and recursively remove allfalse
property values:And then, to deserialize, do:
Notes:
This solution is more robust than a simple string replacement such as
input.Replace("false", "null")
since it is quite possible that the textfalse
may appear within some JSON string.System.Text.Json.Nodes lacks an equivalent to
JContainer.Descendants()
so we have to write one ourselves.Demo #2 here.
I removed
false
properties because it seemed more robust than replacing them withnull
. If you would prefer to replace withnull
you will need to add in aJsonConverter<bool>
that mapsnull
tofalse
forbool
values.And then deserialize like so:
Demo #3 here.