Home > Mobile >  Deserialized JSON object not null for wrong type
Deserialized JSON object not null for wrong type

Time:09-02

If i have the following c# record:

public record MyRecord(string EndPoint, string Id);

and i have some json that i attempt to deserialize to my type:

var myType= JsonSerializer.Deserialize<MyRecord>(
            jsonStr,
            new JsonSerializerOptions
            {
                PropertyNameCaseInsensitive = true
            }
        );

      if(myType is null)
      {
         ...
      }

where jsonStr is not of type MyRecord but some other type, the resulting myType rather then being null, is simply an instance of MyRecord but with empty properties. How can i check that the returned type is invalid if its not null ?

CodePudding user response:

JsonSerializer does not make assumptions about the lack of contents of a json string, provided that it is at least in the same format as the target structure (e.g. "{ }").

As a result, you need to check one of your properties for validity as well as the object itself:

var jsonStr = "{}";

var myType = JsonSerializer.Deserialize<MyRecord>(
        jsonStr,
        new JsonSerializerOptions
        {
            PropertyNameCaseInsensitive = true
        }
    );

if (!string.IsNullOrEmpty(myType?.Id))
{
    var x = myType;
}

Note that the behavior is identical for classes as well:

public class MyClass
{
    public string EndPoint { get; set; }
    public string Id { get; set; }
}

var myType2 = JsonSerializer.Deserialize<MyClass>(
        jsonStr,
        new JsonSerializerOptions
        {
            PropertyNameCaseInsensitive = true
        }
    );

if (!string.IsNullOrEmpty(myType2?.Id))
{
    var x = myType;
}

As mentioned in the comments, you can choose to create a custom converter that overrides the serialization behavior.

public class MyRecordConverter : JsonConverter<MyRecord>
{
    public override MyRecord Read(ref Utf8JsonReader reader, Type typeToConvert, 
        JsonSerializerOptions options)
    {
        if (reader.TokenType != JsonTokenType.StartObject)
        {
            return null;
        }
        
        var endpoint = string.Empty;
        var id = string.Empty;
        
        while (reader.Read())
        {
            if (reader.TokenType == JsonTokenType.EndObject)
            {
                break;
            }
            
            var propertyName = reader.GetString();
            reader.Read();
            
            if (propertyName.Equals(nameof(MyRecord.EndPoint),
                StringComparison.OrdinalIgnoreCase))
            {
                endpoint = reader.GetString();
            }
            else if (propertyName.Equals(nameof(MyRecord.Id), 
                StringComparison.OrdinalIgnoreCase))
            {
                id = reader.GetString();
            }
        }
        
        if (string.IsNullOrEmpty(endpoint) && string.IsNullOrEmpty(id))
        {
            return null;
        }
        
        return new MyRecord(endpoint, id);
    }

    public override void Write(Utf8JsonWriter writer, MyRecord value, 
        JsonSerializerOptions options)
    {
        throw new NotImplementedException();
    }
}

When passed to your Deserialize call:

var myType3 = JsonSerializer.Deserialize<MyRecord>(
        jsonStr,
        new JsonSerializerOptions
        {
            PropertyNameCaseInsensitive = true,
            Converters =
            {
                new MyRecordConverter()
            }
        }
    );

the above empty json object will return null instead of an initialized record.

  • Related