I'm working with a WebApi and XML as result.
I just keep receiving a weird namespace in my result, for exemple:
<QueryId>FE04A4E6-A584-47BF-9DA1-7360DFB08A8D</QueryId>
<ExecutionError>true</ExecutionError>
<OperationResult xmlns:d2p1="http://schemas.datacontract.org/2004/07/MyTypes" i:nil="true"/>
<ErrorMessage>INVALID ACCOUNT</ErrorMessage>
I read some solutions and included this at my WebApiConfig.cs:
config.Formatters.XmlFormatter.UseXmlSerializer = true;
But using this parameter, my return was the same without OperationResult tag (the only one that was not filled out):
<QueryId>FE04A4E6-A584-47BF-9DA1-7360DFB08A8D</QueryId>
<ExecutionError>true</ExecutionError>
<ErrorMessage>INVALID ACCOUNT</ErrorMessage>
I was trying to use my result object like this:
[DataContract(Namespace = "")]
public class CustomRecordResult
{
[DataMember]
public string QueryId { get; set; }
[DataMember]
public bool ExecutionError { get; set; }
[DataMember]
public string ErrorMessage { get; set; }
[DataMember]
public CustomSourceRecord OperationResult { get; set; }
}
But it´s not working. My result object is empty in this case
Any ideas?
Thank you very much!
Use the EmitDefaultValue option to control whether that member will be serialized when it is null.
[DataMember(EmitDefaultValue = false)]
public CustomSourceRecord OperationResult { get; set; }
Related
I have following XML-Data:
<?xml version="1.0"?>
<e:propertyset xmlns:e="urn:schemas-upnp-org:event-1-0">
<e:property>
<LastChange>
<Event xmlns="urn:schemas-upnp-org:metadata-1-0/RCS/">
<InstanceID val="0">
<RoomVolumes val="uuid:29e07ad9-224f-4160-a2bc-61d17845182a=100"/>
<Volume channel="Master" val="100"/>
<Mute channel="Master" val="0"/>
<RoomMutes val="uuid:29e07ad9-224f-4160-a2bc-61d17845182a=0"/>
</InstanceID>
</Event>
</LastChange>
</e:property>
</e:propertyset>
And here are my classes:
[XmlRoot("propertyset", Namespace = "urn:schemas-upnp-org:event-1-0")]
public class EventPropertySet
{
[XmlElement("property")]
public List<EventProperty> Properties { get; set; }
}
public class EventProperty
{
[XmlElement("LastChange")]
public string LastChange { get; set; }
[XmlElement("SinkProtocolInfo")]
public string SinkProtocolInfo { get; set; }
[XmlElement("IndexerStatus")]
public string IndexerStatus { get; set; }
[XmlElement("SystemUpdateID")]
public string SystemUpdateID { get; set; }
}
Now when I try to deserialize the XML-Data 'LastChange' is always 'null'.
When I modify the class 'EventProperty' like so:
public class EventProperty
{
[XmlElement("LastChange", Namespae = "")]
public string LastChange { get; set; }
[XmlElement("SinkProtocolInfo", Namespae = "")]
public string SinkProtocolInfo { get; set; }
[XmlElement("IndexerStatus", Namespae = "")]
public string IndexerStatus { get; set; }
[XmlElement("SystemUpdateID", Namespae = "")]
public string SystemUpdateID { get; set; }
}
The deserialization throws an exception:
XmlException: ReadElementContentAs() methods cannot be called on an element that has child elements. Line 1, position 103.
Any ideas what I should do?
Sorry, I found the problem. The data behind "LastChange" is normaly a parsed XML-Structure (like this:)
<LastChange><Event xmlns="urn:schemas-upnp-org:metadata-1-0/RCS/"><InstanceID val="0"><RoomVolumes val="uuid:29e07ad9-224f-4160-a2bc-61d17845182a=100"/><Volume channel="Master" val="100"/><Mute channel="Master" val="0"/><RoomMutes val="uuid:29e07ad9-224f-4160-a2bc-61d17845182a=0"/></InstanceID></Event></LastChange>
Now when I don't do the "DeParse" with WebUtility.HtmlDecode, everythings works fine.
passing a Json value like this one(this will be the var jsonValue in code):
"{\"Something\":0,\"Something2\":10,\"Something3\":{\"Something4\":17,\"Something5\":38042,\"Something6\":38043,\"Id\":215},\"Something7\":215,\"SomethingId\":42,\"Something8\":\"AString, Gläser\",\"Something8\":\"44-55-18\",\"Status\":{\"Caption\":\"Fixed\",\"Value\":7},\"Type\":\"Article\",\"Id\":97,\"#Delete\":true,\"Something9\":\"8\"}"
to the following code:
var deserializer = new JsonSerializer();
const string regex = #"/Date\((.*?)\+(.*?)\)/";
var reader = new JsonTextReader(new StringReader(jsonValue));
returnValue = deserializer.Deserialize(reader, type);
type is the typeof https://dotnetfiddle.net/LMPEl0 (thank you Craig) (sorry for the weird names, can't disclose the actual ones...)
The jsonvalue is generated by input in an editable cell of a DataTable and apparently places previously null values in the end of the json string.
I get a null value in the "Something9" property in the returnValue, instead of 8(Something9 was null before and set to 8 through an editable Cell of a DataTable)
Is there some problem with the Json value that I can't see?
Or do I need some setting in the Deserializer?
Thanks
You don't show what your type is so I generated one using http://json2csharp.com.
public class Something3
{
public int Something4 { get; set; }
public int Something5 { get; set; }
public int Something6 { get; set; }
public int Id { get; set; }
}
public class Status
{
public string Caption { get; set; }
public int Value { get; set; }
}
public class RootObject
{
public int Something { get; set; }
public int Something2 { get; set; }
public Something3 Something3 { get; set; }
public int Something7 { get; set; }
public int SomethingId { get; set; }
public string Something8 { get; set; }
public Status Status { get; set; }
public string Type { get; set; }
public int Id { get; set; }
[JsonProperty("#Delete")]
public bool Delete { get; set; }
public string Something9 { get; set; }
}
Because one of your properties has a name that is not valid as a .NET property I added the [JsonProperty] attribute to that one. After that it worked perfectly. Perhaps the problem is with how you declared the #Delete JSON property in your .NET type. Given that Something9 comes after that property it would be my guess that that's part of the problem.
Here's the fiddle.
https://dotnetfiddle.net/McZF9Q
While Craig's answer helped a lot and finally led to a solution the exact answer to the problem was the following:
The Status object is an Enum and was not Deserialized correctly.
Due to that, anything that followed in the Json string was also not deserialized.
Implementing a custom Enum Deserializer was the solution. There are other Questions in stackoverflow that helped with this, particularly this one here:
How can I ignore unknown enum values during json deserialization?
Thank you everyone :)
I'm using the Newtonsoft Json (http://james.newtonking.com/json) library to deserialize some json into an object but having some trouble with a boolean value. Please see my example below. The example should run in LinqPad as long as you reference the Newtonsoft dll (I'm using the latest at the moment which has a file version of 6.0.3.17227). The issue is deserializing into the UpdateLocationsRequest object.
Any help is appreciated.
void Main()
{
string json1 = "{\"token\":\"5b2a38c8-c211-481e-aa75-7d52fff6eb2f\",\"share\":true}";
string json2 = "{\"token\":\"5b2a38c8-c211-481e-aa75-7d52fff6eb2f\",\"locationList\":[{\"desc\":\"This is a test\",\"name\":\"Andrew 3\",\"deviceLocationId\":\"a8d2bfae-4493-41cd-ae1e-ea0da66da0cf\",\"locType\":1,\"lon\":-80.27543,\"lat\":43.42618,\"share\":true}]}";
TestClass req1 = JsonConvert.DeserializeObject<TestClass>(json1);
UpdateLocationsRequest req2 = JsonConvert.DeserializeObject<UpdateLocationsRequest>(json2);
json1.Dump("json1");
req1.Dump("Boolean ok here");
json2.Dump("json2");
req2.Dump("Boolean not ok here. Why not?");
}
// Define other methods and classes here
public class UpdateLocationsRequest
{
public string token { get; set; }
public List<LocationJson> locationList { get; set; }
}
public class LocationJson
{
public string deviceLocationId { get; set; }
public string name { get; set; }
public string desc { get; set; }
public int locType { get; set; }
public float lat { get; set; }
public float lon { get; set; }
public bool show { get; set; }
}
public class TestClass {
public string token {get; set;}
public bool share {get; set;}
}
Your json bool value is share, but in your class it's show. Adjust one or the other so they match, and you should be good to go
I found your problem. You LocationJson class has a boolean property named show whiles your json2 string has the property share. show is never updated. All other values are updated.
It is always a good thing to add breakpoints and step into your program and see what is going on.
Best of luck.
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
__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; }
}
}
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; }
}
I've got a class like this
public class Reply
{
public string Result { get; set; }
public int Code { get; set; }
public string Description { get; set; }
}
When I use it as a param to XmlResult constructor, I get an output where xml element names first letters are uppercase. But I need them to be plain lowercase. Perhaps there is some sort of attribute which I miss? Unfortunately, I haven't found any documentation on XmlResult.
For serializing you add either:
[XmlElement("loweredname")]
or
[XmlAttribute("loweredname")]
for XML Elements and Attributes respectively. Hopefully this works for what you need.
Update: Your class should be something like:
[XmlRoot("reply")]
public class Reply
{
[XmlElement("result")]
public string Result { get; set; }
[XmlElement("code")]
public int Code { get; set; }
[XmlElement("description")]
public string Description { get; set; }
}