Search code examples
c#jsonserializationjson.netjson-deserialization

Error Deserializing JSON Object/Array using newtonsoft


I have an json string which contains the following data

"air:FlightOptionsList": {
    "air:FlightOption": [{
            "LegRef": "hx5kk+3R2BKABGzqAAAAAA==",
            "Destination": "LHE",
            "Origin": "DXB",
            "air:Option": {
                "Key": "hx5kk+3R2BKA/FzqAAAAAA==",
                "TravelTime": "P0DT3H0M0S",
                "air:BookingInfo": {
                    "BookingCode": "I",
                    "BookingCount": "7",
                    "CabinClass": "Economy",
                    "FareInfoRef": "hx5kk+3R2BKAzFzqAAAAAA==",
                    "SegmentRef": "hx5kk+3R2BKAtFzqAAAAAA=="
                }
            }
        }, {
            "LegRef": "hx5kk+3R2BKAFGzqAAAAAA==",
            "Destination": "DXB",
            "Origin": "LHE",
            "air:Option": {
                "Key": "hx5kk+3R2BKACGzqAAAAAA==",
                "TravelTime": "P0DT11H30M0S",
                "air:BookingInfo": [{
                        "BookingCode": "U",
                        "BookingCount": "7",
                        "CabinClass": "Economy",
                        "FareInfoRef": "hx5kk+3R2BKA+FzqAAAAAA==",
                        "SegmentRef": "hx5kk+3R2BKAvFzqAAAAAA=="
                    }, {
                        "BookingCode": "Y",
                        "BookingCount": "9",
                        "CabinClass": "Economy",
                        "FareInfoRef": "hx5kk+3R2BKA+FzqAAAAAA==",
                        "SegmentRef": "hx5kk+3R2BKAxFzqAAAAAA=="
                    }
                ],
                "air:Connection": {
                    "SegmentIndex": "0"
                }
            }
        }
    ]
}

my Class Structure is below:

public class FlightOptionsList
{
    public List<FlightOption> FlightOption { get; set; }
}

public class FlightOption
{
    public string LegRef { get; set; }
    public string Destination { get; set; }
    public string Origin { get; set; }
    public Option Option { get; set; }
}

public class Option
{
    public string Key { get; set; }
    public string TravelTime { get; set; }
    public List<BookingInfo> BookingInfo { get; set; }
    public Connection Connection { get; set; }
}

public class BookingInfo
{
    public string BookingCode { get; set; }
    public string BookingCount { get; set; }
    public string CabinClass { get; set; }
    public string FareInfoRef { get; set; }
    public string SegmentRef { get; set; }
}

I want to deserialize it, but its giving me an error as following:

Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'System.Collections.Generic.List`1[ParseSoapEnveloperReqRes.BookingInfo]' because the type requires a JSON array (e.g. [1,2,3]) to deserialize correctly. To fix this error either change the JSON to a JSON array (e.g. [1,2,3]) or change the deserialized type so that it is a normal .NET type (e.g. not a primitive type like integer, not a collection type like an array or List) that can be deserialized from a JSON object. JsonObjectAttribute can also be added to the type to force it to deserialize from a JSON object. Path 'FlightOptionsList.FlightOption[0].Option.BookingInfo.BookingCode', line 394, position 59.

this is because, as if you see the json string, FlightOptionsList.FlightOption[0].Option.BookingInfo is an object but in FlightOptionsList.FlightOption[1].Option.BookingInfo is an array as you can see.

how can I set this problem... I am using the following code to deserialize the json string to class object

 var AirTravelResultModel = JsonConvert.DeserializeObject<AirTravelResultModel>(xmlInputData);

Solution

  • Look at Camilo Martinez answer on this discussion : Deserializing JSON when sometimes array and sometimes object

    Basically, you'll need to add the JsonConverter attribute to your BookingInfo property and handle the conversion in a JsonConverter implementation.

    public class FlightOptionsList
    {
        public List<FlightOption> FlightOption { get; set; }
    }
    
    public class FlightOption
    {
        public string LegRef { get; set; }
        public string Destination { get; set; }
        public string Origin { get; set; }
        public Option Option { get; set; }
    }
    
    public class Option
    {
        public string Key { get; set; }
        public string TravelTime { get; set; }
        [JsonConverter(typeof(SingleValueArrayConverter<BookingInfo>))]
        public List<BookingInfo> BookingInfo { get; set; }
        public Connection Connection { get; set; }
    }
    
    public class BookingInfo
    {
        public string BookingCode { get; set; }
        public string BookingCount { get; set; }
        public string CabinClass { get; set; }
        public string FareInfoRef { get; set; }
        public string SegmentRef { get; set; }
    }
    
    public class Connection
    {
        public string SegmentIndex { get; set; }
    }
    

    And here's the converter :

    public class SingleValueArrayConverter<T> : JsonConverter
    {
        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
            throw new NotImplementedException();
        }
    
        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            object retVal = new Object();
            if (reader.TokenType == JsonToken.StartObject)
            {
                T instance = (T)serializer.Deserialize(reader, typeof(T));
                retVal = new List<T>() { instance };
            }
            else if (reader.TokenType == JsonToken.StartArray)
            {
                retVal = serializer.Deserialize(reader, objectType);
            }
            return retVal;
        }
    
        public override bool CanConvert(Type objectType)
        {
            return true;
        }
    }