C# Constructor from deserialized json? - c#

I have a class which represent a json api. I have created a constructor that is using switched enums to select how the object is to be populated. One is for the minimum equivalent json object. Another is intended populate the properties by reading in from a file. So, I can read the file into a string and deserialize it, but what do I do next to populate the properties?
// this code is in the constructor
string text = System.IO.File.ReadAllText(fileName);
this.???? = JsonConvert.DeserializeObject<MyObject>(text); // MyObject is the object the constructor is working on
Can I cast the deserialized text into the object's properties?
Sorry for asking something that has probably already been asked, but I don't know if I am even asking the question properly (let alone searching for it). Thanks...

Not tested, but I think you could do something like this:
public MyObject(MyEnum e)
{
switch(e)
{
case MyEnum.ValueThatMeansWeDeserializeFromJSON:
string text = System.IO.File.ReadAllText(fileName);
var serializer = new JsonSerializer();
serializer.Populate(new JsonTextReader(new StringReader(text)), this);
break;
}
}
Populate will take an existing object and try to deserialize the properties from JSON into that object (as opposed to DeserializeObject which will create a new object.

As I mentioned in a comment, use a factory instead of the switch in the constructor.
If you want to keep it in the constructor use automaper and do this instead
public class MyObject
{
public MyObject()
{
}
public MyObject(Enum e)
{
string text = System.IO.File.ReadAllText(fileName);
var source = JsonConvert.DeserializeObject<MyObject>(text);
Mapper.CreateMap<MyObject, MyObject>();
Mapper.Map(source, this);
}
public string Name { get; set; }
}

Related

C# Parse/Deserialize JSON partially with Newtonsoft

I have to extract a part of json-string using .net or newtonsoft json.
JSON:
var json = "{\"method\":\"subtract\",\"parameters\":{\"minuend\":\"SOME_CUSTOM_JSON_OBJECT_DIFFERENT_FOR_EACH_METHOD\",\"subtrahend\":23}}";
C# Class:
class MyJson{
public string method { get; set; }
//public string parameters {get; set;}
public object parameters {get; set;}
}
I do not need to parse all the children of "parameters" json-object. "parameters" could be a very big object ([{obj1}...{obj1000}], objX of 1000 fields), parse which would be not performant.
I would like i.e. to pass it exactly as it is on some point, so conversion "string-C#object-string" would be redundant.
I do not want use Regexp or string transformations (string.Substring, Split and co), because of error margin, I know that all .net and newtonsoft string transformations based.
Question 1: if I define a property of type "object", how newtonsoft will handle this? (Documentation is worse than msdn, so I'm looking for the input from you, who already tried this).
static void Main(string[] args)
{
var json = "{\"method\":\"subtract\",\"parameters\":{\"minuend\":42,\"subtrahend\":23}}";
var data = JsonConvert.DeserializeObject<MyJson>(j);
// what internal representaion of data.parameters?
// How is it actually converted from json-string to an C# object (JObject/JsonObject).
}
In perfect case:
"parameters" is a string and calling
ExtractMyJson(jsonString)
gives me the json string of parameters.
Basically I need the newtonsoft version of
string ExtractMyJson(jsonString){
var p1 = jsonString.Split(",");
// .. varios string transformations
return pParams;
}
Note: please don't reference "dynamic" keyword or ask why no string transformations, it's the very specific question.
If you know that your parameters are unique you can do something like this:
class MyJson
{
public string method { get; set; }
public Dictionary<string,object> parameters { get; set; }
}
................
string json = "{\"method\":\"subtract\",\"parameters\":{\"minuend\":{\"img\": 3, \"real\": 4},\"subtrahend\":23}}";
var data = JsonConvert.DeserializeObject<MyJson>(json);
If you let it as object is going to receive the type Newtonsoft.Json.Linq.JObject.
Have you tried JTOKEN?
It is a rather simple solution to partially read basic or nested JSONs as described in this post.
For a nested JSON
{
"key1": {
"key11": "value11",
"key12": "value12"
}
"key2": "value2"
}
it would look like this
JToken token = JToken.Parse(json);
var value12 = token.SelectToken("key1.key12");
to get the element of the key "key12.
I think this could go nicely with your problem.
Well Objects are treated the same way your parent object is treated. It will start from the base of the graph. So if you have something like:
Person
{
Address Address {get;set;}
}
The Json will start Deserializing Address and then add in the Person object.
If you want to limit thesize of the graph depth you can use a setting like :
JsonConvert.DeserializeObject<List<IList<IList<string>>>>(json, new JsonSerializerSettings
{
MaxDepth = 2
});
For more configurations of the JsonSerializer check JsonSerializerSettings
If your field is an object then that object will have the KeyValuePair of every property that it holds, based on that when you cast that field you can access that type.(the behaviour is the same as assigning a type to an object in C#).
Update: So if you question using JsonObject or type, well JObject is and intermediary way to construct the json format in a generic format. But using the Type deserializatin means you can ignore properties you are not interested in. Mapping to a json with a type makes more sense because it creates a new object and dismisses the old JObject.

How to parse non-array JSON?

I am trying to read json from a local .json file and parse the contents using StreamReader and Json.NET. Json & my code:
contents of .json file: {"rate":50,"information":{"height":70,"ssn":43,"name":"andrew"}}
using (var sr = new StreamReader(pathToJsonFile))
{
dynamic jsonArray = JsonConvert.DeserializeObject(sr.ReadToEnd());
foreach(var item in jsonArray)
{
Console.WriteLine(item.rate);
Console.WriteLine(item.ssn);
}
}
This gives me an error on the line foreach(var item in array): Object reference not set to an instance of an object. I am guessing this is because my json is not actually an array but that is how I am trying to parse it. How can I parse this json in order to pull out fields such as rate or ssn?
NB - please do not flag this question as a duplicate of Read and parse a Json File in C#, as that is where I got my original code from.
EDIT: As has been pointed out in other answers, jsonArray is null. That explains my error but still does not answer my question. How else can I parse this json in order to extract the desired fields?
A couple things:
If you want to manually parse out the values, you should try using JObject rather than JsonConvert.DeserializeObject. The following code should work:
dynamic jsonObject = JObject.Parse("{'rate':50,'information':{'height':70,'ssn':43,'name':'andrew'}}");
Console.WriteLine(jsonObject["rate"]);
Console.WriteLine(jsonObject["information"]["ssn"]);
However, if you know how the json is structured, you should create a .net class like:
public class Person
{
public int rate {get;set;}
public Information information {get;set;}
}
public class Information
{
public int height {get;set;}
public int ssn {get;set;}
public string name {get;set;}
}
and then use:
var person = JsonConvert.DeserializeObject<Person>(thestringtodeserialize);
That way you can have a strongly typed object.
In any case, I would check for null (DeserializeObject can obviously return null):
using (var sr = new StreamReader(pathToJsonFile))
{
dynamic jsonArray = JsonConvert.DeserializeObject(sr.ReadToEnd());
if(jsonArray != null) //new check here
{
foreach(var item in jsonArray)
{
Console.WriteLine(item.rate);
Console.WriteLine(item.ssn);
}
}
I am guessing this is because my json is not actually an array
True, the returned object is dynamic, so make use of dynamic:
var json = "{\"rate\":50,\"information\":{\"height\":70,\"ssn\":43,\"name\":\"andrew\"}}";
dynamic obj = JsonConvert.DeserializeObject(json);
Console.WriteLine("rate: {0}. ssn: {1}", obj.rate, obj.information.ssn);
See live sample here: https://dotnetfiddle.net/nQYuyX
Are you sure it's an array?
If that's the format the you expect from Json, maybe you should consider defining a class.
For example:
class SomeJsonObject
{
public int rate {get;set;}
[JsonProperty("information")] //if you want to name your property something else
public InformationObject Information {get;set;}
}
class InformationObject
{
[JsonProperty("height", NullValueHandling = NullValueHandling.Ignore)] //some other things you can do with Json
public int Height {get;set;}
public int ssn {get;set;}
public string name {get;set;}
}
This way you can just deserialize it to an object:
SomeJsonObject jsonArray = JsonConvert.DeserializeObject<SomeJsonObject>(sr.ReadToEnd());
I think your question is similar to this Deserialize JSON with C# . you can use JavaScriptSerializer
I don't get a null reference (with Json.net 6.0.3) but your code has one obvious bug:
static void Main(string[] args)
{
string s = "{'rate':50,'information':{'height':70,'ssn':43,'name':'andrew'}}".Replace('\'', '\"');
var obj = JsonConvert.DeserializeObject(s);
dynamic jsonArray = obj;
foreach (var item in jsonArray)
{
Console.WriteLine(item.rate);
Console.WriteLine(item.ssn);
}
}
The bug is Console.WriteLine(item.rate) will throw.
Your 'array' jsonArray is not actually an array, it is a dictionary!
Therefore, item=the first Key-Value-pair in the dictionary, = {"rate":50}.
You can prevent the code from throwing by getting rid of your foreach loop.
i would fire up nuget and get the JSON.net package
https://www.nuget.org/packages/Newtonsoft.Json/
http://james.newtonking.com/json
it is well documented and can save you a tonne of work.
see also http://json2csharp.com/
EDIT: you are already using this

Determining object "type" during json deserialization

While trying to de-serialize a complex JSON object (JIRA issue) into an object containing a dictionary of type string-Field I've hit a bit of a bump.
While I can de-serialize various pre-determined object types (standard), I'm having a bit of a harder time with the custom fields, which could be of various types (they all begin with customfield_ followed by a set of numbers).
The custom fields can be floats, strings, booleans, objects and arrays of objects. The latter of these is causing me issues since I can't seem to determine what the object is before I de-serialize it.
I've searched for a way to perhaps "peek" at the data in the object before de-serializing as one of the fields contains information specific to it's type. This is all so I can determine the type of the object and tell Json.Net what to de-serialize it as.
I've considered parsing the JSON string before serialization to get the information, or maybe just when hitting this particular case, but maybe there is a better way?
Thanks in advance for any advice on this.
You can deserialize to an object with Json.Net. Here's a quick and dirty example:
using System;
using Newtonsoft.Json;
namespace Sandbox
{
class Program
{
private static void Main(string[] args)
{
var nestDto = new Dto
{
customfield_1 = 20,
customfield_2 = "Test2"
};
var dto = new Dto
{
customfield_1 = 10,
customfield_3 = new[] { nestDto },
customfield_2 = "Test"
};
var jsonString = JsonConvert.SerializeObject(dto);
Console.WriteLine(jsonString);
var fromJsonString = JsonConvert.DeserializeObject<Dto>(jsonString);
Console.WriteLine(fromJsonString.customfield_3[0].customfield_2); //Outputs Test2
Console.ReadKey();
}
}
class Dto
{
public int customfield_1 { get; set; }
public string customfield_2 { get; set; }
public Dto[] customfield_3 { get; set; }
}
}
Instead of peaking, you can deserialize as the same type as JSON.net uses for ExtensionData explicitly. For example:
if (reader.TokenType == JsonToken.StartArray)
{
var values = serializer.Deserialize<List<Dictionary<string, JToken>>>(reader);
objectContainer = ClassifyAndReturn(values);
}
private ObjectType ClassifyAndReturn(List<Dictionary<string, JToken>> values)
{
if (values.First().ContainsKey("self"))
{
string self = values.First()["self"].Value<string>();
if (self.Contains("customFieldOption"))
//... Then go into a series of if else cases to determine the object.
The representation of the objects are given as a Dictionary of string to JToken, which can then easily be checked and assigned manually or in some cases automatically deserialized (in the case one of the fields is another object).
Here is what an object constructor could look like:
internal myobject(Dictionary<string, JToken> source)
{
Self = source["self"].Value<string>();
Id = source["id"].Value<string>();
Value = source["value"].Value<string>();
}

Json Stream in Wcf c# service to array

I'm really bad with C# and would like your help doing the following; I am currently passing a Json Array to my WCF webservice. I need to take the json array and insert it into a list. I have no idea to deserialize in C#. Please suggest to me what is the best way of achieving this. My code looks as follows:
public String UpdateOrderAddress(Stream userInfo)
{
try
{
StreamReader reader = new StreamReader(userInfo);
string JSONdata = reader.ReadToEnd();
if (JSONdata == null)
{
return "null";
}
return JSONdata; // Success !
}
catch (Exception e)
{
return e.ToString();
}
}
This is the data in the string that I get from the reader
[{"date":"2013-02-22 15:30:374:021","id":"1","description":"test","name":"test"},
"date":"2013-02-25 11:56:926:020","id":"2","description":"ghy","name":"fhh"},
"date":"2013-02-25 11:56:248:026","id":"3","description":"ghfm","name":"run"}]
The code you posted doesn't show how are you trying to deserialize your json string so I don't really follow what's the relevance here but in any case, this is how to deserialize JSON into a concrete C# class.
Create a class that matches the structure of your Javascript objects as so:
public class Data
{
public string Date {get;set;}
public int ID {get;set;}
public string Description {get;set;}
public string Name {get;set;}
}
Deserialize it using the JavascriptSerializer as so:
var deserializedData = new JavaScriptSerializer().Deserialize<List<Data>>(jsonString);
Note that your original JSON string is incorrectly formatted. It's missing the opening { on each element of the array. It should really be:
[{"date":"2013-02-22
15:30:374:021","id":"1","description":"test","name":"test"},
{"date":"2013-02-25
11:56:926:020","id":"2","description":"ghy","name":"fhh"},
{"date":"2013-02-25
11:56:248:026","id":"3","description":"ghfm","name":"run"}]
Now, if you attempt to deserialize the above, as so:
string json = #"[{""date"":""2013-02-22 15:30:374:021"",""id"":""1"",""description"":""test"",""name"":""test""},
{""date"":""2013-02-25 11:56:926:020"",""id"":""2"",""description"":""ghy"",""name"":""fhh""},
{""date"":""2013-02-25 11:56:248:026"",""id"":""3"",""description"":""ghfm"",""name"":""run""}]";
var deserializedData = new JavaScriptSerializer().Deserialize<List<Data>>(json);
You'll get a nice List<Data> back.
Also note that I didn't use a DateTime field for the corresponding date field in your Javascript object, the reason being that your sample dates are not valid DateTimes or at least a DateTime object cannot be created from that string representation. For instance, "15:30:374:021" makes no sense - I would imagine that 374 is the seconds field...
You need to add a reference to System.Web.Extensions to be able to use the JavascriptSerializer.
You can create a representative class with your required properties to hold the values and use the JavascriptSerializer class. Call the Deserialize<T> method specifying your type to deserialize the JSON into your code.
Links in class names for reference.
You can use Newtonsoft.Json Library. All you will need to do is:
List<YourClass> yourClassList = JsonConvert.DeserializeObject<List<YourClass>>(JSONdata);
You find more information, even samples here

How to map a data contract to refer to correct fields in a JSON object?

I'm recieving a JSON object that looks like the example below.
{
"name1":{"name1a":"value1a","name1b":"value1b"},
"name2":{"name2a":"value2a","name2b":"value2b"}
}
I've set up a data contract for it (since I only need to access a single data field at the moment) like this.
[DataContract]
public class MyThingy
{
[DataMember(Name="name1b")]
public string Name1b { get; set; }
public MyThingy() { }
public MyThingy(String name1b)
{
Name1b = name1b;
}
}
When I've serialized the object, I try to print it out (which works, since I'm getting a string description of the class) and them the field Name1b. The last part doesn't work and I'm getting null there. My guess is that I must have mapped the data contract wrongly but I can't see how to correct it.
How should the MyThingy class be declared?
My JSON object is fetched as described in this post.
I would use JavaScriptSerializer here,
string json = #"{
""name1"":{""name1a"":""value1a"",""name1b"":""value1b""},
""name2"":{""name2a"":""value2a"",""name2b"":""value2b""}
}";
var obj = new JavaScriptSerializer()
.Deserialize<Dictionary<string, Dictionary<string, string>>>(json);
Console.WriteLine(obj["name1"]["name1b"]);
You can also use Json.Net and dynamic together
dynamic obj = JsonConvert.DeserializeObject(json);
Console.WriteLine(obj.name1.name1b);

Categories