C# ServiceStack JsonSerializer Deserialize - c#

How can I deserialize a string to Json object where the json Object can be a single or an array, right now I have this, which works but its a hack (pseudo):
class MyObject{
public string prop1
public string prop2;
}
class MyList{
List<MyObject> objects {get; set; }
}
class Test{
MyList list = JsonSerialzer.Deserialize<MyList>(str);
//if list is null - it can be single
if(list == null){
MyObject myObject = JsonSerializer.Deserialize<MyObject>(str);
if(myObject != null)
list.add(myObject);
}
}
As shown above, problem is the json String I am receiving from another service can be either single or list. How to handle this elegantly?

I would strongly advise against accepting different structures in the same argument, it makes your software highly brittle and unpredictable. But if it could be a list you can just check the first char is a [, e.g:
if (str.TrimStart().StartsWith("["))
{
MyList list = JsonSerialzer.Deserialize<MyList>(str);
}
else
{
MyObject myObject = JsonSerializer.Deserialize<MyObject>(str);
}
Also please note that by default all ServiceStack text serializers only serialize public properties, so you need to add getters/setters to each property you want serialized, e.g:
class MyObject
{
public string prop1 { get; set; }
public string prop2 { get; set; }
}
class MyList
{
List<MyObject> objects { get; set; }
}
Otherwise you can configure ServiceStack.Text to also serialize public fields with:
JsConfig.IncludePublicFields = true;

Related

Deserialize collection type virtual data member

I'm trying to deserialize json to RequestWithDefault object
JSON:
{
"fields":["f1","f2"]
}
My simple class diagram:
[DataContext]
public abstract class BaseRequest
{
[DataMember]
public virtual List<string> Fields { get; set; }
}
[DataContext]
public class RequestWithDefault : BaseRequest
{
[DataMember]
public override List<string> Fields {get; set; } = new List<string> {"test"}
}
After deserializing json to RequestWithDefault object Fields property contains ["test", "f1", "f1"]. I want to be sure that this default values are applied only in case when Fields were not specified in request, or was specified as null. How I can do this? I tried with [OnDeserializing] attribute but without success. Result is the same
According to this:
https://learn.microsoft.com/en-us/dotnet/framework/wcf/feature-details/collection-types-in-data-contracts
Looks like during deserialization DataContractSerializer calling Add method from collection. That's why I have also default value and rest of items are added. When I will replace List<string> to string[] everything works fine.
It seems WCF serialization never use setter to set the value of the DataMember with type of collection, but use Add instead. Because of this, the only way to check whether the fields has any value is to check after it has been deserialized (not while deserializing).
[DataContext]
public abstract class BaseRequest
{
[DataMember]
public virtual List<string> Fields { get; set; }
}
[DataContext]
public class RequestWithDefault : BaseRequest
{
[System.Runtime.Serialization.OnDeserialized]
void OnDeserialized(System.Runtime.Serialization.StreamingContext c)
{
if (Fields == null
|| Fields.Count < 1)
{
Fields = new List<string> { "test" };
}
}
}

Deserialization of JSON in c#

I have the following JSON
{
"employee" : {
"property1" : "value1",
"property2" : "value2",
//...
}
}
to a class like
public class employee
{
public string property1{get;set;}
public string property2{get;set;}
//...
}
In my JSON if I need to add property3 then I need to make changes in my class too.
How can I deserialize to a class even though if I change my JSON(adding another property like property3).
The serialize/De-serialize techniques like newtonsoft.json is tightly coupled with the Class.
Is there a better way/tool to deserialize these kind of JSON in portable class in c#?
Newtonsoft is not tightly coupled with strong types. You can deserialize the dynamic types too. See the similar question here (How to read the Json data without knowing the Key value)
You can try .net's JavaScriptSerializer (System.Web.Script.Serialization.JavaScriptSerializer). If some field is added or removed it deserializes object normally.
namespace ConsoleApplication8
{
public class Person
{
public int PersonID { get; set; }
//public string Name { get; set; }
public bool Registered { get; set; }
public string s1 { get; set; }
}
class Program
{
static void Main(string[] args)
{
var s = "{\"PersonID\":1,\"Name\":\"Name1\",\"Registered\":true}";
var serializer = new System.Web.Script.Serialization.JavaScriptSerializer();
var o = serializer.Deserialize<Person>(s);
;
}
}
}
If we can use " Dictionary<string,string> employee" the above json can be deserilized.

Deserialize complex object

I'm trying to deserialize an object sent by the browser. My object is array of Detail with the name as key. The name is a string and the detail an object with properties.
this is Picture of the javascript object:
And this is the JSON String I receive, created with "JSON.stringify(TemplateDetails)":
"{\"UDF1-0-div\":{\"UDFtitle\":\"theTitle\",\"DDLType\":\"STRING\",\"defaultValue\":\"defVal\",\"minLength\":\"1\",\"maxLength\":\"6\",\"decimals\":\"\",\"DDLTable\":\"\",\"DDLFilter\":\"\",\"DDLAction\":\"TEST\",\"DDLfontfamily\":\"Verdana\",\"DDLSize\":\"12px\",\"DDLTextAlignment\":\"left\",\"colorTitle\":\"#FFFFFF\",\"colorText\":\"#FFFFFF\"}}"
I want to recreate the object in the c# code.
First of all you should create a class with all of properties you need :
public class MyClass
{
public string DDLAction{ get; set; }
public string DDLFilter{ get; set; }
public string DDLSize{ get; set; }
// put all of your attributes
//...
}
And for deserialization :
System.Web.Script.Serialization.JavaScriptSerializer ser = new System.Web.Script.Serialization.JavaScriptSerializer();
MyClass Obj = ser.Deserialize<MyClass>(input);
That's not a dictionary, a dictionary looks like this:
{
"objName": {
["title", "thetitle"],
["DDLType":"STRING"],
["defaultValue": "defVal"]
}
}
You got a regular object and will have to create it as such.

deserialize json into .net object using json.net

I am having a problem deserializing some JSON string back into .net objects. I have a container class which contains some information from external and there is a field call ClassType which defined what type of information is that and the actual content is in another property, which currently can be anything, so we define that as an Object type.
Following are the .net class definition which helps to understand the issue.
class ClassOne
{
public string Name { get; set; }
public int Age { get; set; }
}
class ClassTwo
{
public string AddressLine { get; set; }
public string AddressLine2 { get; set; }
}
class ClassThree
{
public string Country { get; set; }
public string Passport { get; set; }
}
class ContainerClass
{
public string ClassType { get; set; }
public object ClassContent { get; set; }
}
When getting the information from external in a JSON format it will be something like:
{"ClassType":"Class1","ClassContent":{"Name":"James","Age":2}}
I am using Newtonsoft JSON.net library to deserialize the JSON string. It seems like that the default deserialize function will just deserialize that into an Newtonsoft.Json.Linq.JContainer. I just wondering how can I write some Converter to deserialize the ClassContent based on the ClassType definition. Any code sample will be highly appreciated.
I would go dynamic way, like:
string json = #"{""ClassType"":""Class1"",""ClassContent"":{""Name"":""James"",""Age"":2}}";
dynamic jObj = JObject.Parse(json);
if (jObj.ClassType == "Class1")
{
Console.WriteLine("{0} {1}", jObj.ClassContent.Name, jObj.ClassContent.Age);
}
Since returning an object (ClassContent) doesn't mean much, and you have to cast it to a concrete class somehow (using some if's or switch).
Sample:
var container = JsonConvert.DeserializeObject<ContainerClass>(json);
JContainer content = (JContainer)container.ClassContent;
switch(container.ClassType)
{
case "Class1": return container.ToObject(typeof(ClassOne));
..
}
use dynamic and call .ToObject(Type type)
dynamic root = JObject.Parse(json)
return root["ClassContent"].ToObject(Type.GetType(root["ClassType"]))
Try the following
var jsonObject = JObject.Parse(jsonString);
var result = jsonObject.ToObject(Type.GetType("namespace.className"));

Deserializing JSON with different types for serialization/deserialization

I have a class:
[DataContract]
public class A
{
[DataMember]
public B ArbitraryProperty { get; set;}
}
When serialized, "ArbitraryProperty" needs to be in the form of class "B":
[DataContract]
public class B
{
[DataMember]
public string ValueA { get; set; }
[DataMember]
public string ValueB { get; set; }
}
Here's the JSON output:
{
"ArbitraryProperty": { "ValueA": "I'm a value.", "ValueB": "I'm a value too!" }
}
When I get that same object back from the server though, the property comes back as a simple string like this:
{
"ArbitraryProperty": "I'm not a B, muahahaha!!!"
}
There has to be a trick to letting the DataContractJsonSerializer know that it should deserialize the value to a string instead of a "B".
Is there a special way to set up class "A"? :/
Any suggestions?
I don't think this is the right way to go - I think the right answer for readability and usability is to properly type a request and a response class. But...Only thing I can think of is to make the property an object rather than strongly typing it. You'll just need to ensure that when you assign a value to it, you assign the right type.
public class A
{
public object ArbitraryProperty { get; set; }
}
It will still serialize properly:
var a = new A { ArbitraryProperty = new B { ValueA = "a", ValueB = "b" } };
var json = JsonConvert.SerializeObject(a);
Console.WriteLine(json);
When the object comes back, deserializing will put that string into the property.
json = "{'ArbitraryProperty':'This is some string'}";
a = JsonConvert.DeserializeObject<A>(json);
This code works with simple serialize/deserialize from JSON.NET, but I don't know if WebAPI or whatever technology you're using will like it.

Categories