0

After spending a day reading through posts here I still can't get this to work so hopefully this makes sense to someone here.

The web service returns this simple JSON

{"d":{"__type":"TestWebServices.Person","Name":"Bob","FavoriteColor":"Green","ID":0}}

Then I am using C# code to deserialize

DataContractJsonSerializer jsonSerializer = new DataContractJsonSerializer(typeof(Person));
Person someone = (Person)jsonSerializer.ReadObject(responseStream);

When I use this model someone is created but all the properties are null

[DataContract]
public class Person {
    [DataMember]
    public string Name { get; set; }
    [DataMember]
    public string FavoriteColor { get; set; }
    [DataMember]
    public int ID { get; set; }
}

I tried being more literal and used this model

[DataContract]
public class Person {
    [DataMember]
    public PersonItem d { get; set; }
}
[DataContract]
public class PersonItem {
    [DataMember]
    public string __Type { get; set; }
    [DataMember]
    public string Name { get; set; }
    [DataMember]
    public string FavoriteColor { get; set; }
    [DataMember]
    public int ID { get; set; }
}

And got this error, which I don't even know where to start with

Element ':d' contains data from a type that maps to the name ':GEMiniWebServices.Person'. The deserializer has no knowledge of any type that maps to this name. Consider using a DataContractResolver or add the type corresponding to 'TestWebServices.Person' to the list of known types - for example, by using the KnownTypeAttribute attribute or by adding it to the list of known types passed to DataContractSerializer.

Any thoughts? Thanks

1
  • 1
    If you add a Service Reference, the generated client will deserialize the response for you. Commented May 3, 2012 at 15:18

2 Answers 2

1

__Type should never be part of your object. It's a hint to the serializer. Also, the type hint that you have in your JSON object is bad. Stand-Alone JSON Serialization says:

To preserve type identity, when serializing complex types to JSON a "type hint" can be added, and the deserializer recognizes the hint and acts appropriately. The "type hint" is a JSON key/value pair with the key name of "__type" (two underscores followed by the word "type"). The value is a JSON string of the form "DataContractName:DataContractNamespace" (anything up to the first colon is the name).

The type hint is very similar to the xsi:type attribute defined by the XML Schema Instance standard and used when serializing/deserializing XML.

Data members called "__type" are forbidden due to potential conflict with the type hint.

It works with the following if you rewrite the __type declaration as Person:#TestWebServices or eliminate it:

namespace TestWebServices
{
    [KnownType(typeof(Person))]
    [DataContract]
    public class PersonWrapper
    {
        [DataMember]
        public Person d { get; set; }
    }
    [DataContract]
    public class Person
    {
        [DataMember]
        public string Name { get; set; }
        [DataMember]
        public string FavoriteColor { get; set; }
        [DataMember]
        public int ID { get; set; }
    }
}
Sign up to request clarification or add additional context in comments.

5 Comments

Thanks for the info JamieSee. I had also tried it without the "__type" and got the same error. The web service is creating that type hint, not sure what I can do about that.
Added comment - If I strip out the "d":{"__type":"GEMiniWebServices.Person" from the JSON Both the DataContractJsonSerializer and JavaScriptSerializer have no problem parsing the data into the PersonItem object So is the purpose of "d":{"__type":"? It's obviously making something simple complicated. Thoughts?
This issue is described here codeproject.com/Articles/72443/… The article suggests stripping out the json that is causing the issue.
It works if you rewrite the __type declaration to Person:#TestWebServices or eliminate it.
Here's a question related to the "purpose" of "d" : {.
0

Try adding (and I'm kind of taking a bit of a stab here so the exact namespace my be incorrect)

[DataContract(Namespace = "http://schemas.datacontract.org/2004/07/TestWebServices.Person")]

to your DataContractAttribute on Person.

[DataContract(Namespace = "http://schemas.datacontract.org/2004/07/TestWebServices.Person")]
public class Person {
    [DataMember]
    public PersonItem d { get; set; }
}
[DataContract]
public class PersonItem {
    [DataMember]
    public string __Type { get; set; }
    [DataMember]
    public string Name { get; set; }
    [DataMember]
    public string FavoriteColor { get; set; }
    [DataMember]
    public int ID { get; set; }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.