Search code examples
c#json.netjson.net.net-4.5

Unable to deserialize current JSON array due to field name


I have json (simplified version)

var json = @"{""$type"": ""some type"",""$values"": [{""type"": ""some type"",""Name"": """",""Id"": ""someValue"",}]}";
public class JsonStorage
{
    [JsonProperty("$type")] public string Type { get; set; }
    [JsonProperty("$values")] public List<JsonTest> Values { get; set; }
}

public class JsonTest
{
    [JsonProperty("Name")] public string Name { get; set; }
    [JsonProperty("Id")] public string Id { get; set; }
}

When deserialize

JsonConvert.DeserializeObject<JsonStorage>(json);

Throw exception

Newtonsoft.Json.JsonSerializationException: Cannot deserialize the current JSON array (e.g. [1,2,3]) into type 'Program+JsonStorage' because the type requires a JSON object (e.g. {"name":"value"}) to deserialize correctly.
To fix this error either change the JSON to a JSON object (e.g. {"name":"value"}) or change the deserialized type to an array or a type that implements a collection interface (e.g. ICollection, IList) like List<T> that can be deserialized from a JSON array. JsonArrayAttribute can also be added to the type to force it to deserialize from a JSON array.
Path '$values', line 1, position 34.

If replace in json string $type -> type and $values -> values and set json property for that json, DeserializeObject works fine. I can use that way, replace before deserialization. But maybe there is a better option.

example: https://dotnetfiddle.net/nxZitW


Solution

  • I didn't encounter any problems deserializing the posted data, using the classes that http://quicktype.io made for me when pasting your json in (though it doesn't like the trailing comma)

    namespace WindowsFormsApp3cs
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }
    
            private void SomeButton_Click(object sender, EventArgs e)
            {
                var json = @"{""$type"": ""some type"",""$values"": [{""type"": ""some type"",""Name"": """",""Id"": ""someValue"",}]}";
                var rootClassNameHere = RootClassNameHere.FromJson(json);
            }
        }
    
    
    
        public partial class RootClassNameHere
        {
            [JsonProperty("$type")]
            public string Type { get; set; }
    
            [JsonProperty("$values")]
            public Value[] Values { get; set; }
        }
    
        public partial class Value
        {
            [JsonProperty("type")]
            public string Type { get; set; }
    
            [JsonProperty("Name")]
            public string Name { get; set; }
    
            [JsonProperty("Id")]
            public string Id { get; set; }
        }
    
        public partial class RootClassNameHere
        {
            public static RootClassNameHere FromJson(string json) => JsonConvert.DeserializeObject<RootClassNameHere>(json, WindowsFormsApp3cs.Converter.Settings);
        }
    
        public static class Serialize
        {
            public static string ToJson(this RootClassNameHere self) => JsonConvert.SerializeObject(self, WindowsFormsApp3cs.Converter.Settings);
        }
    
        internal static class Converter
        {
            public static readonly JsonSerializerSettings Settings = new JsonSerializerSettings
            {
                MetadataPropertyHandling = MetadataPropertyHandling.Ignore,
                DateParseHandling = DateParseHandling.None,
                Converters =
                {
                    new IsoDateTimeConverter { DateTimeStyles = DateTimeStyles.AssumeUniversal }
                },
            };
        }
    }