Home > Software design >  How to force a particular property to be deserialized as string instead of number?
How to force a particular property to be deserialized as string instead of number?

Time:02-20

I have different backends giving back almost the same JSON data model except for a nested json object with the id field which sometimes can be a pure number such as:

{ "something": { "id": 1 } }

or a string, such as:

{ "something": { "id": "ex.GUID" } }

plus the model is made of nullables, different System types and custom classes. And I would like those json numbers 1 to be set as"1" always(so the C# class model has the this property as public string Id { get; set; }), possibly for that precise property.

Is there any JsonConverter<T> or property [Attribute] that could handle carefully such parsing/deserialization?

ps: the current JsonConverter<object> answers don't seem to handle well(exceptions) such scenario as described above

CodePudding user response:

I don't think you need to do anything special, just deserialize to your model. Integer will be converted to strings.

void Main()
{
    JsonConvert.DeserializeObject("{ \"something\": { \"id\": 1 } }", typeof(Test)).Dump();
    JsonConvert.DeserializeObject("{ \"something\": { \"id\": \"1\" } }", typeof(Test)).Dump();
}

public class Test
{
    public Something Something { get; set; }
}

public class Something
{
    public string Id { get; set; }
}

CodePudding user response:

You have to use a custom JsonConverter<T> for that.

/// taken from https://www.thecodebuzz.com/system-text-json-create-a-stringconverter-json-serialization/

public class StringConverter : System.Text.Json.Serialization.JsonConverter<string>
{
    public override string Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        if (reader.TokenType == JsonTokenType.Number)
        {
            var stringValue = reader.GetInt32();
            return stringValue.ToString();
        }
        else if (reader.TokenType == JsonTokenType.String)
        {
            return reader.GetString();
        }

        throw new System.Text.Json.JsonException();
    }

    public override void Write(Utf8JsonWriter writer, string value, JsonSerializerOptions options)
    {
        writer.WriteStringValue(value);
    }
}

and register that in the JsonSerializerOptions

var options = new JsonSerializerOptions
    {
        Converters = { new StringConverter() }, 
        PropertyNameCaseInsensitive = true, 
    };

var jsonA = "{ \"something\": { \"id\": \"ex.GUID\" } }";
var a = JsonSerializer.Deserialize<RootObject>(jsonA, options);

var jsonB = "{ \"something\": { \"id\": 1 } }";
var b = JsonSerializer.Deserialize<RootObject>(jsonB, options);

complete example in this fiddle

  • Related