nuander
nuander

Reputation: 1403

Deserializing JSON from ASP.net web service into C# object

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

Upvotes: 0

Views: 1991

Answers (2)

JamieSee
JamieSee

Reputation: 13010

__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; }
    }
}

Upvotes: 1

jaryd
jaryd

Reputation: 871

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; }
}

Upvotes: 0

Related Questions