DataContractJsonSerializer this is nice class added in the .net framework which can be used to serialize/desirealize object into JSON.
Now following is the example i am trying
[Serializable] class User { public string name; public string userId; }
Now following is the output generated
Output : Notice structure where only "name" is expected instead of k__BackingField
Now this is the problem after digging so much i am not sure from where <> and _BackingField is coming ?
{
"<name>k__BackingField":"test user",
"<userId>k__BackingField":100001}
This is just an educated guess. I think it's because you're using public fields instead of properties for name and userid.
Edit: It appears it also has to do with the fact that you are using the [Serializable] attribute instead of [DataContract] and [DataMember]. Check out this post for more detail:
C# automatic property deserialization of JSON
Related
I want to deserialize an xml document to a class, which is genereated by the concerning xsd files. I don't have control over the contents of the xml-file.
During deserialization I run into an exception, because an enum value in the xml document does not meet the requiremnts of the xsd. Instead of breaking, i would like the deserialization to continue and just take the default value for any such errors. Is there any way to accomplish this behaviour?
edit:
For clarification, what i am trying to achieve: I want to read data from digital invoices. So the creation of the xml file is some kind of blackbox and can contain possibly flase values, even if the structure meets the standards. But that does not mean, that every value is flawed in that way. The exception prevents me from reading the correct values so i just want the deserialization to finish by somehow inserting the default values if such an error occurs.
Neither marking the values as obsolete, nor flagging them with XmlIgnore won't work, because the next xml i receive could contain correct values.
I hope that helped clarifying the problem.
Right now, im using the System.Xml.Serialization dll, but im willing to implement any library which can help me achieve the wanted behaviour.
The exception im getting:
"System.InvalidOperationException: Instance validation error: 'x' is
not a valid value for xType.."
The code that throws the exception:
XmlSerializer serializer = new xml.XmlSerializer(typeof(MyType));
MyType invoice = serializer.Deserialize(memoryStream) as MyType;
I know the code does not help very much, so I'll add the enum, that is currently problematic:
public enum PaymentMeansCodeContentType
{
[System.Xml.Serialization.XmlEnumAttribute("10")]
Item10,
[System.Xml.Serialization.XmlEnumAttribute("20")]
Item20,
[System.Xml.Serialization.XmlEnumAttribute("30")]
Item30,
[System.Xml.Serialization.XmlEnumAttribute("48")]
Item48,
[System.Xml.Serialization.XmlEnumAttribute("49")]
Item49,
[System.Xml.Serialization.XmlEnumAttribute("57")]
Item57,
[System.Xml.Serialization.XmlEnumAttribute("58")]
Item58,
[System.Xml.Serialization.XmlEnumAttribute("59")]
Item59,
ZZZ,
}
These are autogenerated from using the xsd command line tool:
https://learn.microsoft.com/de-de/dotnet/standard/serialization/xml-schema-definition-tool-xsd-exe
The xml i need to deserialize provides me with a '1', so clearly an invalid value. Still i need to access the other valid values from the xml and provide means for indicating which values are flawed.
You can mark the member Obsolete
public enum TypeEnum
{
Temperature,
Pressure,
[Obsolete]
Humidity
}
More info - docs
I still wasn't able to find the simple answer I was hoping for but managed to find a work around that worked for me. I ended up validating every enum in the XML file beforehand against the possible values. If the XML did not match the enum i saved the wrong value and node to a validation result set and overwrote the xml with the enum default value.
As Martin mentioned, it's a bit difficult to answer without proper context or sample code. However, you may want to look at the XmlIgnoreAttribute decorator on the property for the model. See the URL & code sample below for more details on how to use:
https://learn.microsoft.com/en-us/dotnet/api/system.xml.serialization.xmlattributes.xmlignore?view=netframework-4.8
using System;
using System.IO;
using System.Xml.Serialization;
// This is the class that will be serialized.
public class Group
{
// The GroupName value will be serialized--unless it's overridden.
public string GroupName;
/* This field will be ignored when serialized--
unless it's overridden. */
[XmlIgnoreAttribute]
public string Comment;
}
You can use Extended Xml Serializer library (avaliable via nuget) instead of the default XmlSerializer, with a custom converter that will set the default value in case of an error.
I suggest you store the value of the Enum as a string, and then parse it yourself. This is relatively simple to implement, here's an example:
public enum MyEnum
{
Default, //The default value to apply in the event of an invalid Enum value
[XmlEnumAttribute("10")]
Item10,
[XmlEnumAttribute("20")]
Item20
}
public class MyClass
{
public string Value { get; set; }
public MyEnum EnumValue => (MyEnum)(typeof(MyEnum).GetFields().FirstOrDefault(f =>
f.GetCustomAttribute<XmlEnumAttribute>()?.Name == Value)?
.GetValue(null) ?? MyEnum.Default);
}
Or if you prefer it you can also set a nullable Enum
public enum MyEnum
{
[XmlEnumAttribute("10")]
Item10,
[XmlEnumAttribute("20")]
Item20
}
public class MyClass
{
public string Value { get; set; }
public MyEnum? EnumValue => (MyEnum?)typeof(MyEnum).GetFields().FirstOrDefault(f =>
f.GetCustomAttribute<XmlEnumAttribute>()?.Name == Value)?
.GetValue(null);
}
I have a POCO class in C# that represents a JSON object:
class
public int id {get; set;}
public string name {get; set;}
public string description {get; set;}
JSON
{
"id" : 1,
"name" : "name",
"description" : "description"
}
Now the json is going to have these properties added:
{
"property_1" : "value_1",
"property_2" : "value_2",
"property_3" : "value_3"
//etc
}
There could be as few as 0 properties and as many as needed but they would all be named property_ and a number.
So for the class I want to have a List<> of some sort instead of hard coding each property individually, but then went returning the Json object (I'm using MVC) I want to split that List<> into individual objects, how can I do that?
Instead of having:
return Json(property_1, property_2, property_3);
I want:
return Json(properties.Split());
If you are using Json.NET for your JSON serialization, you can use the [JsonExtensionData] attribute to capture properties which you have not coded for. Starting with Json.NET 5.0.8, this property affects both serialization and deserialization to ensure your POCO objects support round-tripping.
In practice, I placed this attribute on a field in an abstract base class which all of my model classes are derived from:
ExtensibleJsonObject
You can write your own custom MediaTypeFormatter and insert it to your HttpConfiguration.Formatters collection in front of the standard JsonFormatter, or extend the standard one and replace it entirely. (I'd suggest the former.)
The MediaTypeFormatters give you access to the raw stream as it's comming in, and you can basically do whatever you want with both serialization and deserialization at that point using all of JSON.NET.
I am using a 3rd party server that exposes an API via REST(so it is not possible to change the JSON). The JSON it returns is in a format like:
[
{
"#noun":"tag",
"#version":0,
"#tag":"myFoo"
}
]
I created a C# object to represent this item
public class ResponseItem
{
public string noun {get;set;}
.....
}
however, when I try to use the JavaScriptSerializer to deserialize this object, the properties do NOT get assigned. The serializer seems to be unable to handle the properties with the # symbol in front of the name.
Any ideas on how to solve this?
Ok, so after some finagling, I ditched the JavaScriptSerializer. I switched over to the DataContractJsonSerializer. I then use well defined data contracts and use the DataMember attribute to specify the name.
i.e.
[DataContract]
public class ResponseItem
{
[DataMember(Name="#noun")]
public string Noun {get;set;}
....
}
There may be a better/different way, but this works and is an acceptable solution
I'm writing an application that posts and gets JSON to/from a backend in Visual C# 4.0.
Obviously, the easiest way to serialize/deserialize the JSON is System.Web.Script.Serialization.JavaScriptSerializer, but I'm having a weird error where it's throwing a ArgumentNullException, claiming that type is null.
When the following JSON is deserialized, it works fine:
{"results":[
{"Name":"Western Bulldogs",
"updatedAt":"2011-08-22T09:09:09.673Z",
"Nickname":"Bulldogs",
"RemoteId":44,
"Abbreviation":"WB",
"createdAt":"2011-08-22T09:09:09.673Z",
"objectId":"2iSK8FDTA6"}
]}
However, when deserializing the second one (with the nested dictionary), it fails with the type is null error.
{"results":[
{"EndDate":{"iso":"2011-09-06T00:00:00.000Z","__type":"Date"},
"Name":"Round 24",
"updatedAt":"2011-08-22T08:33:54.119Z",
"RemoteId":800,"createdAt":"2011-08-22T08:33:54.119Z",
"Season":{"className":"Season","__type":"Pointer","objectId":"WnsdqIlrd6"},
"Order":24,
"StartDate":{"iso":"2011-08-30T00:00:00.000Z","__type":"Date"},
"objectId":"bLdBfhagi9"}
]}
For reference, I'm deserializing with the following method for both queries:
JavaScriptSerializer jsSerialise = new JavaScriptSerializer();
ObjectIdContainerList contList = jsSerialise.Deserialize<ObjectIdContainerList>(responseString);
Where ObjectIdContainerList is as follows (note - it does not implement all the properties of the original JSON object because I am only interested in getting the objectId property):
[Serializable]
public class ObjectIdContainerList
{
public ObjectIdContainer[] results { get; set; }
}
[Serializable]
public class ObjectIdContainer
{
public String objectId { get; set; }
}
The first query deserialises without issue with exactly the same code and objects.
Any suggestions? Would I be best off just going to JSON.NET?
I don't understand what's the purpose of ObjectIdContainerList when you should be able to simply do this:
jsSerialise.Deserialize<List<ObjectIdContainer>>(responseString)
and get a List of ObjectIdContainer
I would also make sure that ObjectIdContainer has a property called "__type" that holds a string. I mention it because that's a weird name for a class property in C#.
EDIT: I just saw that you posted the rest of your code...
Are you saying that you expect to be able to deserialize the response string into an array of ObjectIdContainer where ObjectIdContainer only has a property called objectId? I would be very impressed if you can manage to make that work.
I remember Reflector once showed me that the implementation of the JavascriptSerializer basically uses reflection to serialize/deserialize objects; therefore, you need a corresponding class with the same property names as the ones defined in your JSON object or else it will fail.
I feel kind of bad for answering my own question, but I ended up solving the problem by using Json.Net to deserialise the object with almost exactly the same code and it worked.
I'm not inclined to say that this is a bug in the .Net framework, but it kind of feels that way.
Thanks to those who helped!
I'm currently attempting to build a service to retrieve and serialize a Sitecore data item to JSON, so our Javascript code can access Sitecore content data.
I've tried serializing the object directly with JavascriptSerializer and JSON.Net; both broke due to recursion likely due to the various circular references on the child properties.
I've also attempted to serialize the item to XML (via item.GetOuterXml()), then converting the Xml to JSON. The conversion worked fine; but it only retrieves fields that were set on the item itself, not the fields that were set in the _standardvalues. I tried calling item.Fields.ReadAll() before serializing, as well as a foreach loop with calls to item.Fields.EnsureField(Field.id); however, neither resulted in retrieving the missing fields. However, debugging the code; the Fields array appears to contain all inherited fields from its base template as well as the ones set on the item; so I'm guessing GetOuterXml is just ignoring all fields that weren't set specifically on the item.
The more I look at this, the more it looks like I'm going to need a custom model class to encapsulate the data item and the necessary fields, decorate it with the appropriate JSON.Net serialization attributes, and serialize from there. This feels like a dirty hack though.
So before I go down this road; I wanted to know if anyone here had experience serializing Sitecore content items to JSON for client-side consumption, and is there an easier way that I'm missing. Any constructive input is greatly appreciated.
Cheers,
Frank
I would suggest pursuing your approach of creating a custom model class to encapsulate just the item data you need to pass to the client. Then serialize that class to JSON. This cuts down on the amount of data you're sending over the wire and allows you to be selective about which data are being sent (for security reasons).
The CustomItem pattern and partial classes lend themselves to this approach very well. In the code samples below, the .base class is your base custom item wrapper. You can use this class to access fields and field values in a strongly-typed manner. The .instance class could be used for JSON serialization.
By splitting out the properties you want serialized, you have granular control over the data being sent back to the requesting client and you don't have to worry as much about circular references. If you need to make any changes to field definitions, you could simply change your .base class with minimal impact on your JSON serialization.
Hope this helps!
MyCustomItem.base.cs
public partial class MyCustomItem : Sitecore.Data.Items.CustomItem
{
public const string TitleFieldName = "Title";
public MyCustomItem(Item innerItem) : base(innerItem)
{
}
public static implicit operator MyCustomItem(Item innerItem)
{
return innerItem != null ? new MyCustomItem(innerItem) : null;
}
public static implicit operator Item(MyCustomItem customItem)
{
return customItem != null ? customItem.InnerItem : null;
}
public string Title
{
get { return InnerItem[TitleFieldName]); }
}
}
MyCustomItem.instance.cs
[JsonObject(MemberSerialization.OptIn)]
public partial class MyCustomItem
{
[JsonProperty("Title")]
public string JsonTitle
{
get { return Title; }
}
}
I wonder if you wouldn't be better off using an XSLT to recursively build the JSON?