Home > Net >  Deserialize Json document when everything in source is an array, but target object type is not
Deserialize Json document when everything in source is an array, but target object type is not

Time:06-25

I have a JSON object where all properties are arrays regardless of if they really should be or not.

{
   "StringValue": ["mystringvalue"],
   "StringArrayValue": ["value1","value2"],
   "LongValue": [123]
}

Meanwhile, my class knows the types they should actually be

class MyClass {
   public string StringValue {get;set;}
   public string[] StringArrayValue {get;set;}
   public long LongValue {get;set;}
}

When I do JsonSerializer.Deserialize(jsondoc), it fails because it cannot convert the arrays to non-arrays. How can I have the deserializer pick the first value in the returned JSON data if the class type is not an array?

CodePudding user response:

If you don't want to make things too complex, you can make an additional class for the Deserialization

class MyClassOriginalValue {
   public string[] StringValue {get;set;}
   public string[] StringArrayValue {get;set;}
   public long[] LongValue {get;set;}
   
   public MyClass GetMyClass()
   {
        return new MyClass
        {
            StringValue = this.StringValue?.FirstOrDefault(),
            StringArrayValue = this.StringArrayValue,
            LongValue = this.LongValue?.FirstOrDefault() ?? 0
        }
   }
}

Here my results:

void Main()
{
    var jsonOrig = $"{{"   
       "\"StringValue\": [\"mystringvalue\"],"  
       "\"StringArrayValue\": [\"value1\",\"value2\"],"  
       "\"LongValue\": [123]"  
     "}";
    
    var originalJsonValue = JsonSerializer.Deserialize<MyClassOriginalValue>(jsonOrig);
    
    var targetValue  = originalJsonValue.GetMyClass();
    
    Console.WriteLine(JsonSerializer.Serialize(targetValue));
}

CodePudding user response:

One approach would be to map the array values to a backing store that is an array, but add a getter-setter adapter that allows you to use the singular StringValue and LongValue properties transparently. The "original" singular get-set properties themselves will be ignored by Json per [JsonIgnore] attribute.

class MyClass
{
    [JsonPropertyName("StringValue")]
    public string[] StringValueBackingStore { get; set; } = new string[1];

    [JsonIgnore]
    public string StringValue
    {
        get => StringValueBackingStore.FirstOrDefault();
        set
        {
            if(StringValueBackingStore.Length == 1)
            {
                StringValueBackingStore[0] = value;
            }
            else
            {
                Debug.Assert(false, "Expecting array length of 1");
            }
        }
    }
    public string[] StringArrayValue { get; set; }

    [JsonPropertyName("LongValue")]
    public long[] LongValueBackingStore { get; set; } = new long[1];

    [JsonIgnore]
    public long LongValue
    {
        get => LongValueBackingStore.FirstOrDefault();
        set
        {
            if (LongValueBackingStore.Length == 1)
            {
                LongValueBackingStore[0] = value;
            }
            else
            {
                Debug.Assert(false, "Expecting array length of 1");
            }
        }
    }
}

TEST SERDES

static void Main(string[] args)
{
    var myClass = JsonSerializer.Deserialize<MyClass>(jsondoc);
    Console.WriteLine($"{myClass.StringValue} {myClass.LongValue} {string.Join(",", myClass.StringArrayValue)}");

    Console.WriteLine($"\n{JsonSerializer.Serialize(myClass)}");
}

console

  • Related