Deserialize JSON to C# Objects with Childs - c#

I have a JSON string and I need some help to deserialize it.
At the moment my result is always null.
var results = JsonConvert.DeserializeObject<Root>(json);
// result == null
My JSON:
{"First":{"FirstData1":{"date":"2018-01-01","hint":""},
"FirstData2":{"date":"2018-01-06","hint":""}},
"Second":{"SecondData1":{"date":"2018-01-01","hint":""},
"SecondData2":{"date":"2018-01-06","hint":""}}}....
Only on the last Node there is actual property naming...
MyObjects
public class Root
{
public IEnumerable<TempModelRoot> Value{ get; set; }
}
public class TempModelRoot
{
[JsonProperty("Key")]
public string Key { get; set; }
[JsonProperty("Value")]
public List<TempModelChild> Value { get; set; }
}
public class TempModelChild
{
[JsonProperty("Key")]
public string Key { get; set; }
[JsonProperty("Value")]
public TempModelInfo Value { get; set; }
}
public class TempModelInfo
{
[JsonProperty("date")]
public string date { get; set; }
[JsonProperty("hint")]
public string hint { get; set; }
}

In addition to #MX D 's answer, I want to add two more useful model generator sites, which takes JSON as an input and gives appropriate model classes.
Json2Csahrp
JsonUtils
Use, whenever you find difficult to generate complex model classes.

Most likely you are having a mismatch between the model you are trying to deserialize to, and the actual expected model based of the json itself.
A easy way to resolve this is by using a tool such as Quick Types Model Generator(unafiliated) which allows you to generate C# models based upon a provided json file.
After generation you can compare and/or replace your models with the generated models.
To spot and resolve the issue with your model.

Related

How can I deserialize JSON to a custom type which has a property of type IEnumerable<dynamic>?

I'm writing a console app to retrieve JSON data from a 3rd party API. I have no control over the API data structures or functionality.
Several of the calls I make will return multiple 'pages' of data. The data is a collection of objects of a certain type e.g. User.
I have created classes in my app to match the various data types from the API.
public class User
{
[JsonProperty("id")]
public int ID { get; set; }
[JsonProperty("first_name")]
public string FirstName { get; set; }
[JsonProperty("last_name")]
public string LastName { get; set; }
}
public class FooBar
{
[JsonProperty("foo")]
public string Foo { get; set; }
[JsonProperty("bar")]
public string Bar { get; set; }
}
The API response is always in the same format for these calls. While the actual object types in the "data" array will differ depending on what call has been made.
{
"paging":{"page":1},
"data":[{<object>}, {<object>}, {<object>},...]
}
I have created a class to try to deserialize these. The dynamic[] type for the Data property is for illustrative purposes and I am happy to change it if there is a better approach.
public class ApiResponseObject
{
[JsonProperty("paging")]
public Paging PagingInfo { get; set; }
[JsonProperty("data")]
public dynamic[] Data { get; set; }
}
And I would like to have the Data collection resolve to the appropriate type for the objects it contains. e.g.
string userJson = "{\"paging\":{\"page\":1},\"data\":[{\"id\":1,\"first_name\":\"Joe\",\"last_name\":\"Bloggs\"},{\"id\":2,\"first_name\":\"Jane\",\"last_name\":\"Doe\"}]}"; // json string would come from API
string foobarJson = "{\"paging\":{\"page\":1},\"data\":[{\"foo\":\"Lorem\",\"bar\":\"Ipsum\"},{\"foo\":\"Dolor\",\"bar\":\"Amet\"}]}";
var userResponse = JsonConvert.DeserializeObject<ApiResponseObject>(userJson);
var foobarResponse = JsonConvert.DeserializeObject<ApiResponseObject>(foobarJson);
The deserialization succeeds but the Data collection is of type JObject and cannot be cast into the correct type (User, FooBar).
I am trying to avoid having to write specific response object classes for each request if possible.
I will know what type of object I am expecting in the collection when I am requesting it so I could pass that type to the deserializer but I'm not clear on how to achieve that in this particular scenario.
Something like the below psuedo code would be ideal.
var userResponse = JsonConvert.DeserializeObject<ApiResponseObject<User>>(userJson);
Thanks for your help!
You can use the generic type T, like this :
public class ApiResponseObject<T>
{
[JsonProperty("paging")]
public Paging PagingInfo { get; set; }
[JsonProperty("data")]
public T[] Data { get; set; }
}

Deserializing a string property value to a class instance using JSON.Net

I'm deserializing some JSON from a server which is, for the most part, simple:
{
"id": "ABC123"
"number" 1234,
"configured_perspective": "ComplexPerspective[WithOptions,Encoded]"
}
That "configured_perspective" property, however, is an unfortunate case of the server using a weirdly put-together string when a nested object would have been better.
To ease the suffering of our .NET users, I convert this into a custom class in my object model:
public class Example
{
public string id { get; set; }
public int number { get; set; }
public Perspective configured_perspective { get; set; }
}
// Note, instances of this class are immutable
public class Perspective
{
public CoreEnum base_perspective { get; }
public IEnumerable<OptionEnum> options { get; }
public Perspective(CoreEnum baseArg, IEnumerable<OptionEnum> options) { ... }
public Perspective(string stringRepresentation) {
//Parses that gross string to this nice class
}
public static implicit operator Perspective(string fromString) =>
new Perspective(fromString);
public override string ToString() =>
base_perspective + '[' + String.Join(",", options) + ']';
}
As you can see, I've put together a custom class Perspective that converts to and from the JSON string, but I can't seem to get Newtonsoft JSON to automatically convert the string to my Perspective class.
I tried getting it to call the string constructor with the [JsonConstructor] attribute, but it just calls the constructor with null, not with the string value present in the JSON.
I was under the impression (based on https://stackoverflow.com/a/34186322/529618) that JSON.NET would use implicit/explicit string conversion operators to convert a simple string in JSON to an instance of the target type when available, but it seems to ignore it, and just returns the error:
Newtonsoft.Json.JsonSerializationException: Unable to find a constructor to use for type Perspective. A class should either have a default constructor, one constructor with arguments or a constructor marked with the JsonConstructor attribute. Path 'configured_perspective'
I'm trying to avoid resorting to writing a custom JsonConverter for my Example class - I was pretty sure there would be an out-of-the-box way to convert simple string values to a non-string property type, I just haven't found it yet.
I actually wrote out a custom serializer class before doing reading the last of your article, but I then had an idea.
What if we modified example to not serialize it to Perspective? And we were somewhat lazy about it?
public class Example
{
public string id { get; set; }
public int number { get; set; }
public string configured_perspective { get; set; }
private Perspective _configuredPespective;
[JsonIgnore]
public Perspective ConfiguredPerspective => _configuredPerspective == null ? new Perspective(configured_persective) : _configuredPerspective;
}
It's not perfect, and we hold onto the string wasting memory, but it might work for you as a work-around.
Currently I'm using the following variation on #Jlalonde's suggestion - tweaked such that the user experience doesn't change, taking advantage of the fact that JSON.NET looks for private properties as well.
public class Example
{
public string id { get; set; }
public int number { get; set; }
[JsonIgnore]
public Perspective configured_perspective { get; set; }
[DataMember(Name = "configured_perspective")]
private string configured_perspective_serialized
{
get => configured_perspective?.ToString();
set => configured_perspective = value == null ? null : new Perspective(value);
}
}

Modify a JSON string

I have a string in JSON format as follows
string jsonStr = "{"Type":1, "Id":1000,"Date":null,"Group": "Admin","Country":"India","Type":1}";
I want to modify this string so that Id attribute should always be the first. The order of attributes matters.
Is there any way I can modify this string.
I tried searching google but did not find appropriate solution.
Any help would be appreciated.
EDIT:
I also tried to deserialize object using
object yourOjbect = new JavaScriptSerializer().DeserializeObject(jsonStr);
But here also the "type" attribute comes first. I dont find any way to move the attributes within this deserialized object
It's possible. Use the JsonProperty attribute, property Order.
http://www.newtonsoft.com/json/help/html/JsonPropertyOrder.htm.
Let me know if it works.
Instead of attempting to manipulate the order of the outputted JSON and comparing strings, I would transform both JSON strings that you want to compare, into objects and then perform your comparison. You could then compare individual properties or entire objects with something like the following:
void CompareJSON()
{
string json = #"{""Type"":1, ""Id"":1000,""Date"":null,""Group"": ""Admin"",""Country"":""India"",""Type"":1}";
string jsonToCompare = "JSON TO COMPARE";
MyObject myJsonObject = JsonConvert.DeserializeObject<MyObject>(json);
MyObject myJsonObjectToCompare = JsonConvert.DeserializeObject<MyObject>(jsonToCompare);
if (myJsonObject.Id == myJsonObjectToCompare.Id)
{
// Do something
}
}
class MyObject
{
public int Id { get; set; }
public int Type { get; set; }
public DateTime? Date { get; set; }
public string Group { get; set; }
public string Country { get; set; }
}
Please note that this example is carried out using the Newtonsoft.JSON library. More information on the library can be found here.
Just make your JSON into a c# class with Id first and then serialize it again if that is what you need. You do know that you have "Type" twice in the JSON string? In this solution it will get "fixed" so you only have it once as it should be. But if your string really is with two Type this wont work since the strings will be incorrect. If they really are like that you need to do some ugly string manipulation to fix the order but i hope the first string is incorrect only here and not in your code.
private void Test() {
string json = #"{""Type"":1, ""Id"":1000,""Date"":null,""Group"": ""Admin"",""Country"":""India"",""Type"":1}";
JavaScriptSerializer jsonSerializer = new JavaScriptSerializer();
MyJsonObject myJsonObject = jsonSerializer.Deserialize<MyJsonObject>(json);
string s = jsonSerializer.Serialize(myJsonObject);
//Returns: {"Id":1000,"Type":1,"Date":null,"Group":"Admin","Country":"India"}
}
class MyJsonObject {
public int Id { get; set; }
public int Type { get; set; }
public DateTime? Date { get; set; }
public string Group { get; set; }
public string Country { get; set; }
}

Deserialize object using JSON.NET, but put some properties into a member of the class

I am writing a set of data structures to ingest third-party JSON into (no writing out) using JSON.NET.
I have a case for reading some of the top-level JSON elements into a member object of the object being deserialized into.
My JSON:
{
"Id":1
"Checksum":42
"Name":"adam",
"Hair":true
}
My ideal object structure:
public class EntityHeader
{
int Id { get; set; }
int Checksum { get; set; }
}
public class Entity
{
[HeroicJsonAttribute( "Id", "Checksum" )]
public EntityHeader Header { get; set; }
public string Name { get; set; }
public bool Hair { get; set; }
}
Is there a simple way to achieve this? I will have a number of types which will need this, and I'd hate to have to write a JsonConverter for each.
This question has been asked before, here, but the accepted answer doesn't address the question.
Thanks!
An alternative approach would be to use an EntityHeader field in the Entity class as a backing store for private properties which can be deserialized into:
public class EntityHeader
{
int Id { get; set; }
int Checksum { get; set; }
}
public class Entity
{
private EntityHeader m_Header = new EntityHeader();
public EntityHeader Header { get { return m_Header; } }
[JsonProperty]
private int Id { set { m_Header.Id = value; } }
[JsonProperty]
private int Checksum { set { m_Header.Checksum = value; } }
public string Name { get; set; }
public bool Hair { get; set; }
}
Thus, all the properties in the JSON can be read straight into the Entity object, but consumers of Entity objects have access to a "nicely encapsulated" EntityHeader property.
I haven't tested this, and it may even be kludgey, but it would technically work for me (OP). I am still interested in other answers!
Base on your example you could either; use the adapter pattern:
public class EntityJson
{
int Id { get; set; }
int Checksum { get; set; }
public string Name { get; set; }
public bool Hair { get; set; }
}
// quick/poor example
public class EntityAdapter : IEntity
{
public EntityAdapter(EntityJson model)
{
Header = new Header(); // and populate this objects fields
Name = model.Name; // populate other properties
}
public EntityHeader Header { get; set; }
public string Name { get; set; }
public bool Hair { get; set; }
}
Or abuse the fact that json.net ignores properties not available:
var entity = JsonConvert.Deserialze<Entity>();
var header = JsonConvert.Deserialize<EntityHeader>();
entity.Header = header;
I'm going to go ahead and post this answer which is a little bit too long for a comment, so please take this more as an extended comment than an actual attempt to answer your specific question. And of course, you know your requirements best so this is just my considered opinion :)
With that in mind, my advice is:
Don't do this.
I would instead create a simple DTO class that has a 1-1 relationship to the JSON being received; and I'd put all my validation attributes on the properties of that class.
Once I had deserialised the JSON into this simple DTO, I would then use a mapping layer of some kind (roll your own or use Automapper, etc) to map this DTO into a more meaningful structure such as your Entity class.
My reasoning behind this is because unless your Entity class is itself only a simple DTO (in which case it should be as simple as possible and ideally not be a composite) you are mixing OOP and concerns with data mapping concerns; whilst this in and of itself is not such a bad thing, it only serves to increase the complexity of your code.
Consider for example if your incoming JSON ends up with 30 or 40 properties, and you manage to figure out a way (maybe adapting some of the nice techniques from the other answers) to map it to the Entity class. But what about when something goes wrong - it's going to be much easier to reason about, and therefore debug, a process which you have much more control over; it's also going to be much easier to make special adaptations for odd edge cases where the serialiser behaviour just can't help you out
Granted it's a bit of work to write and maintain these DTOs but not that much - Webtools already does this for you
Reference: At the boundaries, Applications are not Object-Oriented

How to map JSON to C# Objects

I am having issues with understanding how to make this happen.
Basically we have an API, the user sends a JSON of the format:
{
"Profile":[
{
"Name":"Joe",
"Last":"Doe",
"Client":{
"ClientId":"1",
"Product":"Apple",
"Message":"Peter likes apples"
},
"Date":"2012-02-14"
}
]
}
I have a class called Profile with parameters Name, Last, and an object as one of its members called Client as well as property Date.
Something like this:
public class Profile {
public string Name {get; set;}
public string Last {get; set;}
public Client client {get; set;}
public DateTime dDate {get; set;}
}
So basically, I am not sure how to grab the JSON and then map it to my object.
Any help with "helping" me understand would be much appreciated.
You can use Json.NET to deserialize your json string as (with some modifications to your classes)
var yourObject = JsonConvert.DeserializeObject<Root>(jsonstring);
public class Root
{
public Profile[] Profile;
}
public class Profile
{
public string Name { get; set; }
public string Last { get; set; }
public Client Client { get; set; }
public DateTime Date { get; set; }
}
public class Client
{
public int ClientId;
public string Product;
public string Message;
}
You can use a JSON library for this, for example Newtonsoft.Json which is free. It will map json to your types automatically.
Sample:
public static T Deserialize<T>(string json)
{
Newtonsoft.Json.JsonSerializer s = new JsonSerializer();
return s.Deserialize<T>(new JsonTextReader(new StringReader(json)));
}
There is also a NuGet package available.
Easiest way I know is to use JSON.Net by newtonsoft.
To make it easier to understand, I always make matching classes in C# with the same name.
Then its easier to deserialize it.
As an example, if it is an array of objects in js, it will map to a list of object with the same names in C#.
As for the date time, its a bit tricky.
Id do the client side validation and Datetime.tryParse in the serverside, itll take care of the dashes or slashes.
var serializer = new JavaScriptSerializer();
List<abc> abcList = serializer.Deserialize<List<abc>>(PassedInJsonString);
I know this is a long time question, but I would like to add one more option, which does not use third party libraries, and only uses stock .Net libraries, and is available from .Net Core 3.1 onwards.
First of all, I leave a link to the official Microsoft documentation (where you will find examples on how to serialize and deserialize json strings): https://learn.microsoft.com/en-us/dotnet/standard/serialization/system-text-json-how-to
Let's build on your example. We have our starting json string:
{
"Profile":[
{
"Name":"Joe",
"Last":"Doe",
"Client":{
"ClientId":"1",
"Product":"Apple",
"Message":"Peter likes apples"
},
"Date":"2012-02-14"
}
]
}
If we build a data structure that can hold that definition, it would be something like:
public class Root
{
public List<Profile> Profile { get; set; }
}
public class Profile
{
public string Name { get; set; }
public string Last { get; set; }
public Client Client { get; set; }
public string Date { get; set; }
}
public class Client
{
public string ClientId { get; set; }
public string Product { get; set; }
public string Message { get; set; }
}
Now, and finally the answer to how to deserialize a json string into a particular object without third party libraries:
Root root = JsonSerializer.Deserialize<Root>(json);
Where json is the variable that contains your json string.
I add another link of interest, the official documentation of the Deserialize(...) method: https://learn.microsoft.com/en-us/dotnet/api/system.text.json.jsonserializer.deserialize
Something that is really useful is the exception that can be thrown, JsonException: https://learn.microsoft.com/en-us/dotnet/api/system.text.json.jsonexception
DataContractJsonSerializer does the job, but it uses more sophisticated format for DateTime serialization.

Categories

Resources