Using JsonConvert.DeserializeObject to deserialize Json to a C# POCO class
Here is a working example.
Keypoints are:
- Declaration of
Accounts
- Use of
JsonProperty
attribute
.
using (WebClient wc = new WebClient())
{
var json = wc.DownloadString("http://coderwall.com/mdeiters.json");
var user = JsonConvert.DeserializeObject<User>(json);
}
-
public class User
{
/// <summary>
/// A User's username. eg: "sergiotapia, mrkibbles, matumbo"
/// </summary>
[JsonProperty("username")]
public string Username { get; set; }
/// <summary>
/// A User's name. eg: "Sergio Tapia, John Cosack, Lucy McMillan"
/// </summary>
[JsonProperty("name")]
public string Name { get; set; }
/// <summary>
/// A User's location. eh: "Bolivia, USA, France, Italy"
/// </summary>
[JsonProperty("location")]
public string Location { get; set; }
[JsonProperty("endorsements")]
public int Endorsements { get; set; } //Todo.
[JsonProperty("team")]
public string Team { get; set; } //Todo.
/// <summary>
/// A collection of the User's linked accounts.
/// </summary>
[JsonProperty("accounts")]
public Account Accounts { get; set; }
/// <summary>
/// A collection of the User's awarded badges.
/// </summary>
[JsonProperty("badges")]
public List<Badge> Badges { get; set; }
}
public class Account
{
public string github;
}
public class Badge
{
[JsonProperty("name")]
public string Name;
[JsonProperty("description")]
public string Description;
[JsonProperty("created")]
public string Created;
[JsonProperty("badge")]
public string BadgeUrl;
}
How can I deserialize JSON into this POCO class?
Here you go:
var root = JsonConvert.DeserializeObject<RootObject>(json);
var userItem = root.results.items
.Select(i => new UserItem
{
id = i.id,
name = i.name,
title = i.title
}).FirstOrDefault();
return userItem;
As you already know, you can't just convert the Item
class into a UserItem
, but you can build one. One thing to note here is that obviously if you only want to return one you'll have to just grab one. Here I've grabbed the first or default. The default would be null
if the list were empty for example.
Deserializing JSON with Newtonsoft, using a specific class
Copy your JSON. Open Visual studio. Create new C# class file. Now Select below menu option:
Edit > Paste Special > Paste JSON as classes
This will create a class as below
public class Rootobject
{
public Datum[] data { get; set; }
}
public class Datum
{
public string type { get; set; }
public string id { get; set; }
}
Now change RootObject
to jsonTask
and deserialise as below
jsonTask test = JsonConvert.DeserializeObject<jsonTask>(strJSON);
How Can I deserialize a json into a structure?
Yet another solution could be to make use of the JsonSchema
First let's redefine your data model:
public abstract class Settings
{
[JsonProperty("id")]
public string Id { get; set; }
[JsonProperty("type")]
public string Type { get; set; }
}
public class SettingsV1 : Settings
{
[JsonProperty("content")]
public string Content { get; set; }
}
public class SettingsV2 : Settings
{
[JsonProperty("content")]
public Content Content { get; set; }
}
public class Content
{
[JsonProperty("id")]
public string Id { get; set; }
[JsonProperty("duration")]
public long Duration { get; set; }
}
- Instead of having a middle man (
ContentStructure
) rather than you can have two separateSettings
versions - The common fields are defined inside the abstract base class
Now, you can use these two versioned classes to define json schemas:
private static JSchema schemaV1;
private static JSchema schemaV2;
//...
var generator = new JSchemaGenerator();
schemaV1 = generator.Generate(typeof(SettingsV1));
schemaV2 = generator.Generate(typeof(SettingsV2));
Finally all you need to do is to do a preliminary check before calling the DeserializeObject
with the proper type:
Settings settings = null;
var semiParsed = JObject.Parse(json);
if (semiParsed.IsValid(schemaV1))
{
settings = JsonConvert.DeserializeObject<SettingsV1>(json);
}
else if (semiParsed.IsValid(schemaV2))
{
settings = JsonConvert.DeserializeObject<SettingsV2>(json);
}
else
{
throw new NotSupportedException("The provided json format is not supported");
}
JsonConvert.DeserializeObject error while deserializing a string
You should be deserializing into the type, not an array of the type. It's a single object containing an array, but the root json is not an array.
var birdRecords = JsonConvert.DeserializeObject<birdDataSolutionVM>(data);
Convert JSON to C# POCO
JObject defines method Parse for this:
JObject json = JObject.Parse(str);
or try for a typed object try:
Foo json = JsonConvert.DeserializeObject<Foo>(str)
Deserialize JSON to C# Classes
Your problem is twofold:
- You don't have a class defined at the root level. The class structure needs to match the entire JSON, you can't just deserialize from the middle.
- Whenever you have an object whose keys can change, you need to use a
Dictionary<string, T>
. A regular class won't work for that; neither will aList<T>
.
Make your classes like this:
class RootObject
{
[JsonProperty("results")]
public Results Results { get; set; }
}
class Results
{
[JsonProperty("jobcodes")]
public Dictionary<string, JobCode> JobCodes { get; set; }
}
class JobCode
{
[JsonProperty("_status_code")]
public string StatusCode { get; set; }
[JsonProperty("_status_message")]
public string StatusMessage { get; set; }
[JsonProperty("id")]
public string Id { get; set; }
[JsonProperty("name")]
public string Name { get; set; }
}
Then, deserialize like this:
RootObject obj = JsonConvert.DeserializeObject<RootObject>(json);
Working demo here
Deserialize a list of lists
you have to create the whole class, not just an array part. try this
Data data=JsonConvert.DeserializeObject<Data>(jsonString )
or if you need just alarmRecords, you don't need D and PagedAlarms classes. try this code
var jsonParsed=JObject.Parse(json);
List<AlarmRecord> alarmRecords=jsonParsed["d"]["paged_alarms"]["alarm_records"].ToObject<List<AlarmRecord>>();
classes
public partial class Data
{
[JsonProperty("d")]
public D D { get; set; }
}
public partial class D
{
[JsonProperty("__type")]
public string Type { get; set; }
[JsonProperty("account_id")]
public string AccountId { get; set; }
[JsonProperty("message")]
public object Message { get; set; }
[JsonProperty("paged_alarms")]
public PagedAlarms PagedAlarms { get; set; }
}
public partial class PagedAlarms
{
[JsonProperty("__type")]
public string Type { get; set; }
[JsonProperty("alarm_records")]
public List<AlarmRecord> AlarmRecords { get; set; }
}
public partial class AlarmRecord
{
[JsonProperty("__type")]
public string Type { get; set; }
[JsonProperty("alarm_record_details")]
public List<AlarmRecordDetail> AlarmRecordDetails { get; set; }
[JsonProperty("lat")]
public double Lat { get; set; }
[JsonProperty("lon")]
public double Lon { get; set; }
[JsonProperty("time")]
public string Time { get; set; }
}
public partial class AlarmRecordDetail
{
[JsonProperty("__type")]
public string Type { get; set; }
[JsonProperty("active")]
public bool Active { get; set; }
[JsonProperty("code")]
public string Code { get; set; }
[JsonProperty("color")]
public string Color { get; set; }
[JsonProperty("title")]
public string Title { get; set; }
}
How do I deserialize JSON where there is an array of ane/value properties along with a Location which has three values?
just change a type of a value property from string to object and add Location class
public class PropertyAttribute
{
public string name { get; set; }
private object _value;
public object value
{
get
{
if (_value as JObject !=null)
return ((JObject)_value).ToObject<Location>();
return _value?.ToString();
}
set { _value = value; }
}
}
public class Location
{
public int alt { get; set; }
public double lat { get; set; }
public double lon { get; set; }
}
how to use
var propertyChangeData = JsonConvert.DeserializeObject<CustomEventModel>(requestBody);
Location location = (Location) propertyChangeData.properties.Where(p => p.name=="Location").FirstOrDefault().value;
string DeviceSerialNumber = (string) propertyChangeData.properties.Where(p => p.name=="DeviceSerialNumber").FirstOrDefault().value;
Newtonsoft.Json.JsonSerializationException: C#
In your Root
class, change the List<Data> data
to Data data
and then you can de-serialize your JSON
string as required to your Root
class:
using System;
using Newtonsoft.Json;
public class Program
{
public static void Main()
{
string jsonString = "{\"data\":{\"merchantRefNo\":\"foo\"," +
"\"responseText\":\"Approved\"," +
"\"status\":\"A\"," +
"\"txnDate\":\"20220321\"," +
"\"txnId\":\"000067\"," +
"\"txnTime\":\"1049\"," +
"\"txnType\":\"sale\"," +
"\"amt\":\"109\"}," +
"\"dataType\":\"trans\"}";
var result =JsonConvert.DeserializeObject<Root>(jsonString);
Console.WriteLine(result.dataType);
Console.WriteLine(result.data.merchantRefNo);
Console.WriteLine(result.data.status);
Console.WriteLine(result.data.txnId);
}
}
public class Data
{
public string merchantRefNo { get; set; }
public string responseText { get; set; }
public string status { get; set; }
public string txnDate { get; set; }
public string txnId { get; set; }
public string txnTime { get; set; }
public string txnType { get; set; }
public string amt { get; set; }
}
public class Root
{
public Data data { get; set; }
public string dataType { get; set; }
}
Output:
trans
foo
A
000067
You can find a working example here: https://dotnetfiddle.net/8Nsl9m
Related Topics
Getting Image Dimensions Without Reading the Entire File
Restarting (Recycling) an Application Pool
How to Access Named Capturing Groups in a .Net Regex
How to Set an SQL Server Connection String
How to Bind a Tabcontrol to a Collection of Viewmodels
The Cast to Value Type 'Int32' Failed Because the Materialized Value Is Null
Hide Console Window from Process.Start C#
Detailed Explanation of Variable Capture in Closures
Lifetime of ASP.NET Static Variable
How to Create a Dynamic Button Click Event on a Dynamic Button
Regular Expression for Finding 'Href' Value of a <A> Link
Start a .Net Process as a Different User
Copying from and to Clipboard Loses Image Transparency
Remove Weird Characters ( a with Hat) from SQL Server Varchar Column
Why File.Readalllinesasync() Blocks the UI Thread