Newtonsoft json deserialization - key as property - c#

I have a json file :
...
"Key1": {
"Base": 123,
"Max": 1234
},
"Key2": {
"Base": 123,
"Max": 1234
},
"Key3": {
"Base": 123,
"Max": 1234
},
...
I need to deserialize it into an object with JsonConvert.DeserializeObject<T>(__json);
But I need to use the keys (Key1, Key2, Key3,...) as a property of my deserialized object.
Unfortunately, I can't use an alternate deserialization method and I can't modify the json format.
My object is like that
public class Item {
public string Id { get; set; }
public int Base { get; set; }
public int Max { get; set; }
}
My Id's should be "Key1", "Key2, ...
is it possible?

Make a custom Key class:
public class Key {
public int Base { get; set; }
public int Max { get; set; }
}
Then store each item in the JSON result in a Dictionary where it's key is the key name and it's value is a Key item:
var keyCollection = new Dictionary<string, Key>();
//you can then do stuff such as:
var maxOfKeyOne = keyCollection["Key1"].Max;
var baseOfKeyTwo = keyCollection["Key2"].Base;

Related

How to get values from array of JSON in C#

I am new to JSON processing by NewtonSoft on C#. I have the following JSON and trying to get all orderIds and orderNumbers. I tried the following code. But in both cases, I am getting can't access child items error. I also tried using JObject.Parse(json) and tried to get the two values, but got similar errors.
{
"orders": [{
"orderId": 123,
"orderNumber": "234",
"billTo": {
"name": "John1 Doe1",
"Street": "1 one way"
},
"items": [{
"orderItemId": 46429,
"lineItemKey": "110",
"sku": "Hammer",
"name": "Small Hammer"
}]
},
{
"orderId": 567,
"orderNumber": "789",
"billTo": {
"name": "John2 Doe2",
"Street": "2 second way"
},
"items": [{
"orderItemId": 76567,
"lineItemKey": "213",
"sku": "Tape",
"name": "Electric Tape"
}]
},
{
"orderId": 223,
"orderNumber": "334",
"billTo": {
"name": "John3 Doe4",
"Street": "3 third way"
},
"items": [{
"orderItemId": 87890,
"lineItemKey": "890",
"sku": "Box",
"name": "Wooden box"
}]
}
]
}
dynamic dynJson = JsonConvert.DeserializeObject(json);
foreach (var item in dynJson)
{
//Console.WriteLine("{0} {1} \n", item["orders"].orderId,
item["orders"].orderNumber);
Console.WriteLine("{0} {1} \n", item["orders"]["orderId"], item["orders"]
["orderNumber"]);
}
I made it to works as follows:
var jObj = JObject.Parse(json);
JArray orders = (JArray)jObj["orders"];
foreach (JToken order in orders)
{
string orderId = (string)order["orderId"];
string orderNumber = (string)order["orderNumber"];
}
The for loop statement seems to be wrong since dynJson is an object and not an array. You need to loop through the dynJson.orders, like below.
dynamic dynJson = JsonConvert.DeserializeObject(data);
foreach (var item in dynJson.orders)
{
//Console.WriteLine("{0} {1} \n", item["orders"].orderId,
//item["orders"].orderNumber);
Console.WriteLine("{0} {1} \n", item.orderId,
item.orderNumber);
}
}
Above code will print out
123 234
567 789
223 334
You may want to do this in a strongly typed fashion. In that case, you need to create a few classes that can be used to hold your information.
Starting at the deepest end of the hierarchy, first the item:
public class Item
{
public int orderItemId { get; set; }
public string lineItemKey { get; set; }
public string sku { get; set; }
public string name { get; set; }
}
Then the Bill To information:
public class BillTo
{
public string name { get; set; }
public string Street { get; set; }
}
Then an order, which has a BillTo and a bunch of Items:
public class Order
{
public int orderId { get; set; }
public string orderNumber { get; set; }
public BillTo billTo { get; set; }
public List<Item> items { get; set; }
}
and then, because your JSON starts with an object containing a bunch of orders:
public class Orders
{
public List<Order> orders { get; set; }
}
If you run this:
var result = JsonConvert.DeserializeObject<Orders>(theJson);
foreach (var order in result.orders)
{
Debug.WriteLine($"Order #{order.orderId}: For {order.billTo.name}, {order.items.Count} items");
}
You end up with:
Order #123: For John1 Doe1, 1 items
Order #567: For John2 Doe2, 1 items
Order #223: For John3 Doe4, 1 items
While Vinit's answer will no doubt work, we generally try to avoid using dynamic in C#. When we use dynamic, it erases some of the advantages of strongly typed coding, which is one of the great things about C#.
So instead, we can define types to represent our data:
class PostedOrders
{
public List<Order> Orders { get; set; }
}
class Order
{
public int OrderId { get; set; }
public string OrderNumber { get; set; }
public BillRecipient BillTo { get; set; }
public List<Item> Items { get; set; }
}
class BillRecipient
{
public string Name { get; set; }
public string Street { get; set; }
}
class Item
{
public int OrderItemId { get; set; }
public string LineItemKey { get; set; }
public string Sku { get; set; }
public string Name { get; set; }
}
Now that we have defined everything, we get the full benefits of Intellisense, code completion, type checking, and easy refactoring.
To work with the JSON, we can simply iterate through the array. And to write it out to the console, we can use string interpolation which has a nicer syntax than the old format strings.
PostedOrders orders = JsonConvert.DeserializeObject<PostedOrders>(json);
foreach (var order in orders.Orders)
{
Console.WriteLine($"{order.OrderId} {order.OrderNumber}");
}

Desalinizing JSON Object Contains List of Objects Returns Null for the nested object

This is my first attempt of working with JSON deserialization. I have read many of the posts in Stackoverflow, non of the suggested solutions could match my issue, so my apology in advance. I have created the following objects:
public class Item
{
public int ID { get; set; }
public int LSum { get; set; }
public int YSum { get; set; }
public int TSum { get; set; }
public int NSum { get; set; }
public int MemberId { get; set; }
}
public class Something
{
public int Id { get; set; }
public string Phone { get; set; }
public bool ExistingMember { get; set; }
public IList<Item> Item { get; set; }
}
And when deserialize the JSON it looks like following:
The follwoing JSON what I expect it to be:
{
"Id":62,
"Phone":"07",
"ExistingMember":true,
"Item":[
{
"ID":42,
"LSum":0,
"YSum":0,
"TSum":0,
"NSum":0,
"MemberId":12
}
]
}
However the following method it
some= JsonConvert.DeserializeObject<something>(someResponse);
It prints the json like the following:
The following JSON is what is "someResponse" return,
{
"Id":62,
"Phone":"07",
"ExistingMember":true,
"Item":null
}
What am I missing that the item list is return null?
If you want to deserialize json string which in your case is someResponse variable, then you are doing it right.
To check your code I created a JSON file with a file.json name and put the following on it:
{
"Id": 62,
"Phone": "07",
"ExistingMember": true,
"Item": [
{
"ID": 42,
"LSum": 0,
"YSum": 0,
"TSum": 0,
"NSum": 0,
"MemberId": 12
}
]
}
Then below lines of code take the content of JSON file (which in your case is the content of someResponse) and deserialize it into c# object of Something type:
string jsonFilePath = #"C:\test\file.json";
var some = JsonConvert.DeserializeObject<Something>(File.ReadAllText(jsonFilePath));
Then print the ID property of each element of Item list:
foreach(var item in some.Item)
{
if (item != null)
{
Console.WriteLine($"item ID = {item.ID}");
}
}
The output:
item ID = 42
So, it is quite possible that someResponse just does not have an Item and looks like this:
{
"Id": 62,
"Phone": "07",
"ExistingMember": true
}
UPDATE:
Also I tried like this:
var someResponse = #"{
'Id': 62,
'Phone': '07',
'ExistingMember': true,
'Item':[
{
'ID': 42,
'LSum': 0,
'YSum': 0,
'TSum': 0,
'NSum': 0,
'MemberId': 12
}
]
}
";
var some = JsonConvert.DeserializeObject<Something>(someResponse);
And some has a Item list with 1 element

Json parse sub-collection in c#

How can I do JSON in C# like the data below ?
{
"Aliases": [ "teddy", "freddy", "eddy", "Betty" ],
"Name":"reacher gilt",
"Address":"100 East Way",
"Age":74,
"Bars": {
"items": [
{
"Sub_Property1":"beep",
"Sub_Property2":"boop"
},
{
"Sub_Property1":"meep",
"Sub_Property2":"moop"
},
{
"Sub_Property1":"feep",
"Sub_Property2":"foop"
}
]
}
}
Actually my problem is inside the sub-collection. I saw someone did something
like this
person.Bars.Add("items",
new List<BarClass>(new[]{
new BarClass("beep","boop"),
new BarClass("meep","moop"),
new BarClass("feep","foop"),
}));
So, I have to add new BarClass("beep","boop"), but I need to do something
like this
String [] no1 = {1,2,3}
String [] no2 = {4,5,6}
person.Bars.Add("items",
new List<BarClass>(new[]{
for ()
{
new BarClass(no1[i],no2[i])
}
}));
How can i do this? Thanks and please help..
To read the JSON
The best way to read the whole JSON is to Deserialize it to a native C# object. If you do not already have the classes with your, you can create it in Visual Studio as
Copy your JSON text
Create a new empty class file in VS
Edit > Paste Special > Paste JSON As Classes
Here are the classes
public class Person
{
public string[] Aliases { get; set; }
public string Name { get; set; }
public string Address { get; set; }
public int Age { get; set; }
public Bars Bars { get; set; }
}
public class Bars
{
public Item[] items { get; set; }
}
public class Item
{
public string Sub_Property1 { get; set; }
public string Sub_Property2 { get; set; }
}
Now you can use some .NET JSON library to deserialize. JSON.Net aka Newtonsoft JSON is a great library. You get get it from NuGet as well.
Then it's pretty easy to get the C# object from the JSON
//using Newtonsoft.Json;
var jsonString = File.ReadAllText(#"C:\YourDirectory\person.json");
var person = JsonConvert.DeserializeObject<Person>(jsonString);
If you want to read the sub-collection only, you can rather use Linq-to-JSON to read the items directly, like this
//using Newtonsoft.Json.Linq;
var jObject = JObject.Parse(jsonString);
List<Item> details = jObject["Bars"]["items"].ToObject<List<Item>>();
To create the JSON
You first need to create the object, then Serialize to JSON
string[] subProperties1 = new string[] { "1", "2", "3" };
string[] subProperties2 = new string[] { "4", "5", "6" };
Person person = new Person { Name = "Johny", Age = 7, Address = "Earth", Aliases = new string[] { "Sony", "Monty" } };
person.Bars = new Bars {
items = subProperties1.Zip(subProperties2,
(prop1, prop2) => new Item { Sub_Property1 = prop1, Sub_Property2 = prop2 })
.ToArray() };
var json = JsonConvert.SerializeObject(person);
To create the items from your existing string arrays, I have used IEnumerable.Zip function from Linq. You can read about them here.
This is the created JSON data
{
"Aliases": [ "Sony", "Monty" ],
"Name": "Johny",
"Address": "Earth",
"Age": 7,
"Bars": {
"items": [
{
"Sub_Property1": "1",
"Sub_Property2": "4"
},
{
"Sub_Property1": "2",
"Sub_Property2": "5"
},
{
"Sub_Property1": "3",
"Sub_Property2": "6"
}
]
}
}
You should create some classes
public class Person
{
public string Name {get;set;}
public string Address{get;set;}
public int Age {get;set;}
public Header {get;set;}
}
public class Header
{
public Detail[] Details {get;set;}
}
public class Detail
{
public string Sub1 {get;set;}
public string Sub2 {get;set;}
}
Create instance from Person class and initialize to instance after than
JavaScriptSerializer serializer =new JavaScriptSerializer();
var result=serializer.Serialize(instanceOfPerson);
"result" is json data
Assuming that you mean you want to create JSON string, you need to create those classes and use something like Newtonsoft JSON.net:
public class Item
{
public string Sub_Property1 { get; set; }
public string Sub_Property2 { get; set; }
}
public class Bars
{
public List<Item> items { get; set; }
}
public class Person
{
public List<string> Aliases { get; set; }
public string Name { get; set; }
public string Address { get; set; }
public int Age { get; set; }
public Bars Bars { get; set; }
}
Please read the documentation here: http://www.newtonsoft.com/json/help/html/Introduction.htm

Read JSON string as key value

I have following json:
{
"serverTime": "2013-08-12 02:45:55,558",
"data": [
{
"key1": 1,
"key2": {},
"key3": {
"key4": [
""
],
"key5": "test2"
},
"key7": 0
},
{
"key8": 1,
"key9": {},
"key10": {
"key4": [
""
],
"key9": "test2"
},
"key11": 0
}
]
}
I want to get values as key value pair. Something like:
jsonObject[data][0]
should give first item of the data array.
I am using JSONFx.net. But it gives strongly typed objects. I do not want that.
Is there any way to parse JSON as key value as I mentioned earlier?
Thanks
Try this:
using System;
using System.IO;
using Newtonsoft.Json;
class Program
{
static void Main(string[] args)
{
var json = File.ReadAllText("input.txt");
var a = new { serverTime = "", data = new object[] { } };
var c = new JsonSerializer();
dynamic jsonObject = c.Deserialize(new StringReader(json), a.GetType());
Console.WriteLine(jsonObject.data[0]);
}
}
If you're not averse to using Json.NET, you can do this:
var jsonString = #"
{
""serverTime"": ""2013-08-12 02:45:55,558"",
""data"": [
{
""key1"": 1,
""key2"": {},
""key3"": {
""key4"": [
""""
],
""key5"": ""test2""
},
""key7"": 0
},
{
""key8"": 1,
""key9"": {},
""key10"": {
""key4"": [
""""
],
""key9"": ""test2""
},
""key11"": 0
}
]
}";
var jsonResult = JsonConvert.DeserializeObject<Dictionary<string, dynamic>>(jsonString);
var firstItem = jsonResult["data"][0];
firstItem would be an array of the first item in the data array:
Hope this helps.
First create classes to parse string
public class Key2
{
}
public class Key3
{
public List<string> key4 { get; set; }
public string key5 { get; set; }
}
public class Key9
{
}
public class Key10
{
public List<string> key4 { get; set; }
public string key9 { get; set; }
}
public class Datum
{
public int key1 { get; set; }
public Key2 key2 { get; set; }
public Key3 key3 { get; set; }
public int key7 { get; set; }
public int? key8 { get; set; }
public Key9 key9 { get; set; }
public Key10 key10 { get; set; }
public int? key11 { get; set; }
}
public class RootObject
{
public string serverTime { get; set; }
public List<Datum> data { get; set; }
}
add reference of Newtonsoft.Json.dll
RootObject obj = JsonConvert.DeserializeObject<RootObject>(jsonData);
then you can access values .
If you want to do this without third party libraries then do:
I would use the following code:
var deserializer = new JavaScriptSerializer();
var someObject = deserializer.DeserializeObject(json);
string serverTime = someObject["serverTime"].ToString();
Dictionary<string, int> data = someObject["data"] as Dictionary<string, int>;
Give it a go.
Edit: You may need to change the last line to:
Dictionary<string, int?> data = someObject["data"] as Dictionary<string, int?>;

Deserializing array of enum values wih JSON.NET

I'm trying to use JSON.NET to deserialize a response from a third-party web service. This is the full code of my (contrived) example showing what I'm trying to do:
namespace JsonNetTests
{
public enum Parameter
{
Alpha = 1,
Bravo = 2,
Charlie = 3,
Delta = 4
}
public class ResponseElement
{
public int Id { get; set; }
public string Name { get; set; }
[JsonProperty(ItemConverterType = typeof(StringEnumConverter))]
public Parameter[] Parameters { get; set; }
}
public class ResponseBody
{
public string Locale { get; set; }
public string[] Errors { get; set; }
public ResponseElement[] ResponseElements { get; set; }
}
[TestFixture]
public class JsonNetTest
{
[Test]
public void TestEnumArray()
{
string jsonResponse = #"
{""ResponseBody"": {
""Locale"": ""en-US"",
""Errors"": [],
""ResponseElements"": [{
""Id"": 1,
""Name"": ""ABC"",
""Parameters"" : {
""Parameter"" : ""Alpha""
},
}, {
""Id"": 2,
""Name"": ""BCD"",
""Parameters"" : {
""Parameter"" : ""Bravo""
},
}
]
}}
";
JObject rootObject = JObject.Parse(jsonResponse);
JToken rootToken = rootObject.SelectToken("ResponseBody");
JsonSerializerSettings settings = new JsonSerializerSettings();
settings.MissingMemberHandling = MissingMemberHandling.Error;
ResponseBody body = JsonConvert.DeserializeObject<ResponseBody>(rootToken.ToString(), settings);
foreach (var element in body.ResponseElements)
{
Console.WriteLine(string.Format("{0}: {1}", element.Id, element.Name));
foreach (var parameter in element.Parameters)
{
Console.WriteLine(string.Format("\t{0}", parameter));
}
}
}
}
}
I get the following exception:
Newtonsoft.Json.JsonSerializationException : Cannot deserialize JSON object (i.e. {"name":"value"}) into type 'JsonNetTests.Parameter[]'.
The deserialized type should be a normal .NET type (i.e. not a primitive type like integer, not a collection type like an array or List) or a dictionary type (i.e. Dictionary).
To force JSON objects to deserialize add the JsonObjectAttribute to the type. Path 'ResponseElements[0].Parameters.Parameter', line 9, position 21.
I tried to use the ItemConverterType attribute to specify how the array should be deserialised:
[JsonProperty(ItemConverterType = typeof(StringEnumConverter))]
But this does not help either. Can someone advise?
You're trying to stuff an object into an array. ResponseElement.Parameters is an array of enums where you're json code is using an object to describe each parameter.
Your json looks like this:
// some json
"Parameters" : {
"Parameter" : "Alpha"
},
// more json
But to translate it into an array of enums it should look like this:
// some json
"Parameters" : [ "Alpha", "Bravo" ],
// more json
If you can't change the json, you can change your model as so:
public enum ParameterEnum
{
Alpha = 1,
Bravo = 2
}
public ParameterContainer
{
[JsonProperty(ItemConverterType = typeof(StringEnumConverter))]
public ParameterEnum Parameter {get;set;}
}
public class ResponseElement
{
public int Id { get; set; }
public string Name { get; set; }
public ParameterContainer[] Parameters { get; set; }
}
Effectively, you'll serialize the json into an array of ParameterContainers which will expose their values.

Categories

Resources