skip to Main Content

I receive a series of json files which are not standarized, and a specific field is always a number, but sometimes quoted and sometimes unquoted.

e.g: sometimes:

{
  "skinname": "Classic Red",
  "drivername": "",
  "country": "",
  "team": "",
  "number": "0",
  "priority": 4
}

sometimes:

{
    "skinname": "Racing 125",
    "drivername": "",
    "country": "",
    "team" : "Audi Motorsport",
    "number": 125
}

And worst case:

{
  "skinname": "",
  "drivername": "",
  "country": "",
  "team": "",
  "number": "",
  "priority": 1
}

I use System.Text.Json.JsonSerializer.Deserialize<>(), deserialized to this class:

public class JsonLiveryDetails
    {
        public string skinname { get; set; }
        public string drivername { get; set; }
        public string country { get; set; }
        public string team { get; set; }
        public string number { get; set; }
        public int? priority { get; set; }
    }

I have a class to deserialize into, but of course, sometimes I get an error whether I assign that value as string or int.

I cant’t get to handle it in the get; set; of the field, so I workarounded it by catching the error, trying to deserialize it into a class with the other type and then convert the second class into the first, or catching a final error…

I find my workaround dirty, maybe (probabliy) there is a better way to handle it.

EDIT: Following Serge comments, added more details.
EDIT2: Found another case, where number is "" and makes proposed solution to fail

2

Answers


  1. Declare the property as int and use the JsonNumberHandling attribute on the class or individual property to allow automatic casting from string to integer.

    [JsonNumberHandling(JsonNumberHandling.AllowReadingFromString)]
    public class JsonLiveryDetails
    {
        public string skinname { get; set; }
        public string drivername { get; set; }
        public string country { get; set; }
        public string team { get; set; }
        public int number { get; set; }
        public int? priority { get; set; }
    }
    

    See Serge’s answer in order to be able to also handle empty strings.

    Login or Signup to reply.
  2. you can try this converter

    JsonLiveryDetails details = JsonSerializer.Deserialize<JsonLiveryDetails>(json);
    
    public class IntToStringConverter : System.Text.Json.Serialization.JsonConverter<string>
    {
        public override string Read(ref Utf8JsonReader reader, Type type, JsonSerializerOptions options)
        {
            if (reader.TokenType == JsonTokenType.Number)
                 return  reader.GetInt32().ToString();
          
            return reader.GetString();
        }
       
        public override void Write(Utf8JsonWriter writer, string value, JsonSerializerOptions options)
        {
            writer.WriteStringValue(value.ToString());
        }
    }
    
    public class JsonLiveryDetails
    {
        public string skinname { get; set; }
        public string drivername { get; set; }
        public string country { get; set; }
        public string team { get; set; }
        [System.Text.Json.Serialization.JsonConverter(typeof(IntToStringConverter))]
        public string number { get; set; }
        public int? priority { get; set; }
    }
    

    or maybe it make sense to change number property type to int

    public class StringToIntConverter : System.Text.Json.Serialization.JsonConverter<int?>
    {
        public override int? Read(ref Utf8JsonReader reader, Type type, JsonSerializerOptions options)
        {
            if (reader.TokenType == JsonTokenType.String)
            {
                var str = reader.GetString();
    
                if (!string.IsNullOrEmpty(str)
                  && int.TryParse(str, out int val)) return val;
                else return default(int?);
            }
            return reader.GetInt32();
        }
    
        public override void Write(Utf8JsonWriter writer, int? value, JsonSerializerOptions options)
        {
            if (value != null)
                writer.WriteNumberValue((int)value);
                else writer.WriteNullValue();
        }
    }
    
    public class JsonLiveryDetails
    {
        public string skinname { get; set; }
        public string drivername { get; set; }
        public string country { get; set; }
        public string team { get; set; }
    [System.Text.Json.Serialization.JsonConverter(typeof(StringToIntConverter))]
        public int? number { get; set; }
        public int? priority { get; set; }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search