0

I have universal app where I communicate with REST API. Any response from REST I deserialize with DataContractJsonSerializer.

I have a problem with response that contains dictionary. This dictionary I don't need deserialize - my class doesn't contains this dictionary. In Win RT it works, but in Win Phone it doesn't works. I get this error:

The dictionary cannot be deserialized because the member 'key of dictionary' was found more than once in the input.

I don't understand why it works in Win RT and not in Win Phone.

//edit - add sample JSON

{
  "ResultType": 0,
  "Message": "",
  "Exception": null,
  "Result": {
    "property": 1,
    "property2": 2,
    "property3": "2015-01-31T13:56:43.5337609+01:00",
    "GeneratedQuestions": {
      "className": [
        {
          "innerProperty": 1,
          "innerProperty2": 2,
          "innerProperty3": "sample",
          "innerProperty4": [
            {
              "prop1": 1,
              "prop2": 2,
              "prop3": 3,
              "prop4": "sample text",
            }
          ]
        },
        {
          "innerProperty": 1,
          "innerProperty2": 2,
          "innerProperty3": "sample2",
          "innerProperty4": []
        },
        {
          "innerProperty": 1,
          "innerProperty2": 2,
          "innerProperty3": "sample3",
          "innerProperty4": []
        }
      ]
    }
  }
}

code for deserialize json

 protected T DeserializeJson<T>(string json)
            where T : class
        {
            T type;
            DataContractJsonSerializer jsonSerialized = new DataContractJsonSerializer(typeof(T), new DataContractJsonSerializerSettings { DateTimeFormat = new System.Runtime.Serialization.DateTimeFormat("dd.mm.yyyy HH:mm:ss", System.Globalization.CultureInfo.InvariantCulture) });

            using (MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(json)))
            {
                try
                {
                    ms.Position = 0;
                    type = jsonSerialized.ReadObject(ms) as T;
                }
                catch
                {
                    type = default(T);
                }
            }

            return type;
        }

Simplified version of Model:

[DataContract]
public class SampleClass
{
     [DataMember(Name = "ResultType")
     public string ResultType { get; set; }

     [DataMember(Name = "Message")
     public string Message{ get; set; }

     [DataMember(Name = "Exception")
     public Exception Exception{ get; set; }

     [DataMember(Name = "Result")
     public ResultModel Result{ get; set; }
}

public class ResultModel
{
     [DataMember(Name = "property")
     public int Property { get; set; }

     [DataMember(Name = "property2")
     public int Property2 { get; set; }

     [DataMember(Name = "property3")
     public string Property3 { get; set; }
}
Flow
  • 133
  • 7
  • Please show us the json. – Jan Köhler Jan 31 '15 at 13:59
  • I added simplified version of JSON. I have a problem with **GeneratedQuestions** - It's dictionary and I don't need it. – Flow Jan 31 '15 at 14:13
  • Could you additionally post your model you're deserializing to (`T`)? – Jan Köhler Jan 31 '15 at 14:29
  • I added simplified version of JSON. These models I need fill and I need ignore GeneratedQuestions. – Flow Jan 31 '15 at 14:41
  • 1) Is this problem still reproducible after adding `[DataContract]` to `ResultModel` and removing `GeneratedQuestions` from `ResultModel`? 2) `GeneratedQuestions` isn't a dictionary, it's a class containing a single property: `public List className { get; set; }`. Post your JSON into http://json2csharp.com/ to see what I mean. – dbc Jan 31 '15 at 20:37
  • Hi, yes this problem is exists when I added **[DataContract]** to ResultModel and removing **GeneratedQuestions**. It's really not a dictionary but in SOAP same method return dictionary and I automatic implement Model with dictionary. My bad, Thank you very much for your note and useful page which you sent. – Flow Feb 02 '15 at 17:53

1 Answers1

1

I think the error lies in the missing [DataContract]-attribute on ResultModel which tells the serializer to serialize all public members:

Apply the IgnoreDataMemberAttribute attribute to opt-out of the default DataContractSerializer behavior. By default, the DataContractSerializer serializes all publicly visible types. All public read/write properties and fields of the type are serialized. You can change the default behavior by applying the DataContractAttribute and DataMemberAttribute attributes to the types and members

So either put that [DataContract]-attribute on ResultModel or mark GeneratedQuestions as [IgnoreDataMember].

Well the latter is no option for you as you don't have that property in your model. Just to mention that second option.

Jan Köhler
  • 5,817
  • 5
  • 26
  • 35