Home > database >  Newtonsoft C# Convert JSON with different types in one array to Entity
Newtonsoft C# Convert JSON with different types in one array to Entity

Time:06-29

I want to convert/map a JSON result that can have a selection of different types in its properties;

For example:

"randomProperties": [
    {
        "name": "foo",
        "value": 22
    },
    {
        "name": "bar",
        "value": "somestring"
    },  
    {
        "name": "foobar",
        "value": {
          "type": "sometype",
          "currency": "EUR",
          "amount": 20,
        }
    },
    {
        "name": "entity",
        "value": {
          "typeId": "key-value-document",
          "id": "36cxx0f3-6b76-4d7b-8ea7-577fe44ab308"
        }
    }
]

I would like to convert this to this model:

public class RandomProperties
{
    [JsonProperty("name")]
    public string Name { get; set; }

    [JsonProperty("value")]        
    public ValueObject ValueObject { get; set; }

    [JsonProperty("value")]        
    public int? ValueInt { get; set; }
    
    [JsonProperty("value")]        
    public string ValueString { get; set; }
}

public class ValueObject
{
    [JsonProperty("type")]
    public string Type { get; set; }

    [JsonProperty("currency")]
    public string Currency { get; set; }

    [JsonProperty("amount")]
    public int? Amount { get; set; }

    [JsonProperty("typeId")]
    public string TypeId { get; set; }

    [JsonProperty("id")]
    public string ValueId { get; set; }
}

I tried to use the JsonConverter, but i could only manage to keep one of the types. How would I map a random result like this?

CodePudding user response:

It would look something like this:

namespace QuickType
{
    using System;
    using System.Collections.Generic;

    using System.Globalization;
    using Newtonsoft.Json;
    using Newtonsoft.Json.Converters;

    public partial class RandomProperties
    {
        [JsonProperty("randomProperties")]
        public RandomProperty[] RandomPropertiesRandomProperties { get; set; }
    }

    public partial class RandomProperty
    {
        [JsonProperty("name")]
        public string Name { get; set; }

        [JsonProperty("value")]
        public ValueUnion Value { get; set; }
    }

    public partial class ValueClass
    {
        [JsonProperty("type", NullValueHandling = NullValueHandling.Ignore)]
        public string Type { get; set; }

        [JsonProperty("currency", NullValueHandling = NullValueHandling.Ignore)]
        public string Currency { get; set; }

        [JsonProperty("amount", NullValueHandling = NullValueHandling.Ignore)]
        public long? Amount { get; set; }

        [JsonProperty("typeId", NullValueHandling = NullValueHandling.Ignore)]
        public string TypeId { get; set; }

        [JsonProperty("id", NullValueHandling = NullValueHandling.Ignore)]
        public string Id { get; set; }
    }

    public partial struct ValueUnion
    {
        public long? Integer;
        public string String;
        public ValueClass ValueClass;

        public static implicit operator ValueUnion(long Integer) => new ValueUnion { Integer = Integer };
        public static implicit operator ValueUnion(string String) => new ValueUnion { String = String };
        public static implicit operator ValueUnion(ValueClass ValueClass) => new ValueUnion { ValueClass = ValueClass };
    }

    internal static class Converter
    {
        public static readonly JsonSerializerSettings Settings = new JsonSerializerSettings
        {
            MetadataPropertyHandling = MetadataPropertyHandling.Ignore,
            DateParseHandling = DateParseHandling.None,
            Converters =
            {
                ValueUnionConverter.Singleton,
                new IsoDateTimeConverter { DateTimeStyles = DateTimeStyles.AssumeUniversal }
            },
        };
    }

    internal class ValueUnionConverter : JsonConverter
    {
        public override bool CanConvert(Type t) => t == typeof(ValueUnion) || t == typeof(ValueUnion?);

        public override object ReadJson(JsonReader reader, Type t, object existingValue, JsonSerializer serializer)
        {
            switch (reader.TokenType)
            {
                case JsonToken.Integer:
                    var integerValue = serializer.Deserialize<long>(reader);
                    return new ValueUnion { Integer = integerValue };
                case JsonToken.String:
                case JsonToken.Date:
                    var stringValue = serializer.Deserialize<string>(reader);
                    return new ValueUnion { String = stringValue };
                case JsonToken.StartObject:
                    var objectValue = serializer.Deserialize<ValueClass>(reader);
                    return new ValueUnion { ValueClass = objectValue };
            }
            throw new Exception("Cannot unmarshal type ValueUnion");
        }

        public override void WriteJson(JsonWriter writer, object untypedValue, JsonSerializer serializer)
        {
            var value = (ValueUnion)untypedValue;
            if (value.Integer != null)
            {
                serializer.Serialize(writer, value.Integer.Value);
                return;
            }
            if (value.String != null)
            {
                serializer.Serialize(writer, value.String);
                return;
            }
            if (value.ValueClass != null)
            {
                serializer.Serialize(writer, value.ValueClass);
                return;
            }
            throw new Exception("Cannot marshal type ValueUnion");
        }

CodePudding user response:

try this, and you will have to fix classes too

    var randomPropertiesParsed = JObject.Parse(json); 

    var rp = new RandomProperties();
    foreach (JObject item in (JArray)randomPropertiesParsed["randomProperties"])
    {
        switch (item["value"].Type.ToString())
        {
            case "String":
                rp.ValueString = item.ToObject<ValueString>();
                break;

            case "Integer":
                rp.ValueInt = item.ToObject<ValueInt>();
                break;

            case "Object":
                if (item["value"]["type"] != null)
                    rp.ValueObjectType = item.ToObject<ValueObject>();
                else
                    rp.ValueObjectTypeId = item.ToObject<ValueObject>();
                break;
        }
    }

classes

public class RandomProperties
{

    public ValueObject ValueObjectType { get; set; }

    public ValueObject ValueObjectTypeId { get; set; }

    public ValueInt ValueInt { get; set; }

    public ValueString ValueString { get; set; }
}
public class ValueInt
{
    [JsonProperty("name")]
    public string Name { get; set; }
    [JsonProperty("value")]
    public int value { get; set; }
}
public class ValueString
{
    [JsonProperty("name")]
    public string Name { get; set; }
    [JsonProperty("value")]
    public string value { get; set; }
}
public class ValueObject
{
    [JsonProperty("name")]
    public string Name { get; set; }
    [JsonProperty("value")]
    public ValueOfObject value { get; set; }

}
public class ValueOfObject
{
    [JsonProperty("type")]
    public string Type { get; set; }

    [JsonProperty("currency")]
    public string Currency { get; set; }

    [JsonProperty("amount")]
    public int? Amount { get; set; }

    [JsonProperty("typeId")]
    public string TypeId { get; set; }

    [JsonProperty("id")]
    public string ValueId { get; set; }
}
  • Related