1

I'm trying to use JSON.NET to deserialize a response from a third-party web service. This is the full code of my (contrived) example showing what I'm trying to do:

namespace JsonNetTests
{
public enum Parameter
{
    Alpha = 1,
    Bravo = 2,
    Charlie = 3,
    Delta = 4
}

public class ResponseElement
{
    public int Id { get; set; }

    public string Name { get; set; }

    [JsonProperty(ItemConverterType = typeof(StringEnumConverter))]
    public Parameter[] Parameters { get; set; }
}

public class ResponseBody
{
    public string Locale { get; set; }
    public string[] Errors { get; set; }
    public ResponseElement[] ResponseElements { get; set; }
}

[TestFixture]
public class JsonNetTest
{
    [Test]
    public void TestEnumArray()
    {
        string jsonResponse = @"
{""ResponseBody"": {
""Locale"": ""en-US"",
""Errors"": [],
""ResponseElements"": [{
    ""Id"": 1,
    ""Name"": ""ABC"",
    ""Parameters"" : {
        ""Parameter"" : ""Alpha""
    },
    }, {
    ""Id"": 2,
    ""Name"": ""BCD"",
    ""Parameters"" : {
        ""Parameter"" : ""Bravo""
    },
    }
]
}}
";

        JObject rootObject = JObject.Parse(jsonResponse);
        JToken rootToken = rootObject.SelectToken("ResponseBody");

        JsonSerializerSettings settings = new JsonSerializerSettings();
        settings.MissingMemberHandling = MissingMemberHandling.Error;

        ResponseBody body = JsonConvert.DeserializeObject<ResponseBody>(rootToken.ToString(), settings);

        foreach (var element in body.ResponseElements)
        {
            Console.WriteLine(string.Format("{0}: {1}", element.Id, element.Name));
            foreach (var parameter in element.Parameters)
            {
                Console.WriteLine(string.Format("\t{0}", parameter));
            }
        }
    }
}
}

I get the following exception:

Newtonsoft.Json.JsonSerializationException : Cannot deserialize JSON object (i.e. {"name":"value"}) into type 'JsonNetTests.Parameter[]'. The deserialized type should be a normal .NET type (i.e. not a primitive type like integer, not a collection type like an array or List) or a dictionary type (i.e. Dictionary). To force JSON objects to deserialize add the JsonObjectAttribute to the type. Path 'ResponseElements[0].Parameters.Parameter', line 9, position 21.

I tried to use the ItemConverterType attribute to specify how the array should be deserialised:

[JsonProperty(ItemConverterType = typeof(StringEnumConverter))]

But this does not help either. Can someone advise?

j-bennet
  • 310
  • 3
  • 11

1 Answers1

0

You're trying to stuff an object into an array. ResponseElement.Parameters is an array of enums where you're json code is using an object to describe each parameter.

Your json looks like this:

// some json
"Parameters" : {
    "Parameter" : "Alpha"
},
// more json

But to translate it into an array of enums it should look like this:

// some json
"Parameters" : [ "Alpha", "Bravo" ],
// more json

If you can't change the json, you can change your model as so:

public enum ParameterEnum 
{
    Alpha = 1,
    Bravo = 2
}

public ParameterContainer
{
    [JsonProperty(ItemConverterType = typeof(StringEnumConverter))]
    public ParameterEnum Parameter {get;set;}
}

public class ResponseElement
{
    public int Id { get; set; }

    public string Name { get; set; }

    public ParameterContainer[] Parameters { get; set; }
}

Effectively, you'll serialize the json into an array of ParameterContainers which will expose their values.

Thinking Sites
  • 3,494
  • 17
  • 30
  • Thank you for the response! The type that I'm trying to deserialize into is not of my making. It is automaically generated based on that third party's web service's WSDL. They provide both SOAP nad JSON versions of their API, and I would like to reuse classes from SOAP's Reference.cs. – j-bennet May 22 '12 at 19:52
  • I could write my own classes to deserialize into, but I'm trying to avoid it because the third party's classes are HUGE (not at all like my simplified example), they have 30+ properties, most of them complex. Is there any way to achieve the deserialization without changing of the JSON (not possible) or the proxy class, just using the attributes (or perhaps a custom converter)? – j-bennet May 22 '12 at 19:52
  • Wow. Let me think about it and I'll get back to you. – Thinking Sites May 22 '12 at 20:16
  • This may be helpful too: http://stackoverflow.com/questions/23366364/how-do-i-deserialize-an-array-of-enum-using-json-net – Haukman Aug 05 '14 at 01:07