how to access nested object in JSON string - c#

I am getting an API response in JSON format as follows:
{
"token_type":"Bearer",
"access_token":"12345678910",
"user":{
"id":123456,
"username":"jbloggs",
"resource":2,
"firstname":"joe"
}
}
dynamic usrdetail = JsonConvert.DeserializeObject(JSONString);
I can use usrdetail to access token_type and access_token (usrdetail.access_token) but how do I reach the user information?
I have tried usrdetail.user.id but that doesnt work?
Thanks
G

JSON objects are written in key/value pairs. Therefore, to access JSON objects, you can use the square brackets and place the key in it.
So for your example, you can do usrdetail["user"]["id"] which should retrieve the user's id.

1) Create quick type for your json string from json2csharp
public class User
{
public int id { get; set; }
public string username { get; set; }
public int resource { get; set; }
public string firstname { get; set; }
}
public class Token
{
public string token_type { get; set; }
public string access_token { get; set; }
public User user { get; set; }
}
2) Then Deserialize your json into above quick type like
class Program
{
static void Main(string[] args)
{
string json = #"{ 'token_type':'Bearer','access_token':'12345678910','user':{
'id':123456,'username':'jbloggs','resource':2,'firstname':'joe'}
}";
Token token = JsonConvert.DeserializeObject<Token>(json);
Console.WriteLine("token_type: " + token.token_type);
Console.WriteLine("access_token: " + token.access_token);
Console.WriteLine();
Console.WriteLine("id: " + token.user.id);
Console.WriteLine("username: " + token.user.username);
Console.WriteLine("resource: " + token.user.resource);
Console.WriteLine("firstname: " + token.user.firstname);
Console.ReadLine();
}
}
Output:

This should work.
var jsonStr = "{ \"token_type\":\"Bearer\",\"access_token\":\"12345678910\",\"user\":{\"id\":123456,\"username\":\"jbloggs\",\"resource\":2,\"firstname\":\"joe\"}}";
dynamic jsonObject = JsonConvert.DeserializeObject(jsonStr);
int userId = jsonObject.user.id;
Console.WriteLine(userId);
See this: https://dotnetfiddle.net/huKNpU

you can serialize your dynamic object dynamic usrdetail and then deserialize it to a predefined object like below:
dynamic usrdetail = JsonConvert.DeserializeObject(JSONString);
var jsonParam = JsonConvert.SerializeObject(usrdetail);
PredefiendClass obj = JsonConvert.DeserializeObject<PredefiendClass>(jsonParam);

Related

Parse JSON String into List

It is needed to parse JSONString into List. (List of instances)
I'm trying to use JSON.NET by Newtonsoft.
I have classes:
public class Item
{
public int ID { get; set; }
public string Name { get; set; }
public string Url { get; set; }
public string Manufactorers { get; set; }
}
The JSON string looks something like this:
[
{
"Column0":23.0,
"Column1":"Евроен",
"Column2":"https://www.123.com",
"Column3":"Фак"
},
{
"Column0":24.0,
"Column1":"Еил",
"Column2":"https://www.123.com",
"Column3":"Старт"
}
]
I've been trying to do something like this:
string JSONString = string.Empty;
JSONString = JsonConvert.SerializeObject(result);
List<Item> items = JsonConvert.DeserializeObject<List<Item>>(JSONString);
But it returns 0 and null.
I have no idea, how to fix it.
Also here I truy to parse Excel file. This code works, but after deserialization, I have just 0 and null.
var filePath = #"..\..\..\..\doc.xlsx";
using (var steam = File.Open(filePath, FileMode.Open, FileAccess.Read))
{
using (var reader = ExcelReaderFactory.CreateReader(steam))
{
var result = reader.AsDataSet().Tables["Лист1"];
string JSONString = string.Empty;
JSONString = JsonConvert.SerializeObject(result);
List<Item> items = JsonConvert.DeserializeObject<List<Item>>(JSONString);
}
}
The naming of JSON and your class does not match. This can be fixed using JsonProperty attributes:
[JsonProperty("Column0")]
public decimal ID { get; set; }
Second, JSON deserizlizer can not deserialize string "23.0" to int when there is decimal point. You can retype ID to decimal or double to make it work.
Little test here:
public class TestClass
{
[JsonProperty("Column0")]
public decimal ID { get; set; }
}
Then the deserialization works without errors:
var testClassJson = "{\"Column0\": 12.0}";
var i = JsonConvert.DeserializeObject<TestClass>(testClassJson);

Converting JSON array

I am attempting to use the Newtonsoft JSON library to parse a JSON string dynamically using C#. In the JSON is a named array. I would like to remove the square brackets from this array and then write out the modified JSON.
The JSON now looks like the following. I would like to remove the square bracket from the ProductDescription array.
{
"Product": "123",
"to_Description": [
{
"ProductDescription": "Product 1"
}
]
}
Desired result
{
"Product": "123",
"to_Description":
{
"ProductDescription": "Product 1"
}
}
I believe I can use the code below to parse the JSON. I just need some help with making the modification.
JObject o1 = JObject.Parse(File.ReadAllText(#"output.json"));
The to_Description property starts off as List<Dictionary<string,string>> and you want to take the first element from the List.
So, given 2 classes
public class Source
{
public string Product {get;set;}
public List<Dictionary<string,string>> To_Description{get;set;}
}
public class Destination
{
public string Product {get;set;}
public Dictionary<string,string> To_Description{get;set;}
}
You could do it like this:
var src = JsonConvert.DeserializeObject<Source>(jsonString);
var dest = new Destination
{
Product = src.Product,
To_Description = src.To_Description[0]
};
var newJson = JsonConvert.SerializeObject(dest);
Note: You might want to check there really is just 1 item in the list!
Live example: https://dotnetfiddle.net/vxqumd
You do not need to create classes for this task. You can modify your object like this:
// Load the JSON from a file into a JObject
JObject o1 = JObject.Parse(File.ReadAllText(#"output.json"));
// Get the desired property whose value is to be replaced
var prop = o1.Property("to_Description");
// Replace the property value with the first child JObject of the existing value
prop.Value = prop.Value.Children<JObject>().FirstOrDefault();
// write the changed JSON back to the original file
File.WriteAllText(#"output.json", o1.ToString());
Fiddle: https://dotnetfiddle.net/M83zv3
I have used json2csharp to convert the actual and desired output to classes and manipulated the input json.. this will help in the maintenance in future
First defined the model
public class ToDescription
{
public string ProductDescription { get; set; }
}
public class ActualObject
{
public string Product { get; set; }
public List<ToDescription> to_Description { get; set; }
}
public class ChangedObject
{
public string Product { get; set; }
public ToDescription to_Description { get; set; }
}
Inject the logic
static void Main(string[] args)
{
string json = "{\"Product\": \"123\", \"to_Description\": [ { \"ProductDescription\": \"Product 1\" } ]} ";
ActualObject actualObject = JsonConvert.DeserializeObject<ActualObject>(json);
ChangedObject changedObject = new ChangedObject();
changedObject.Product = actualObject.Product;
changedObject.to_Description = actualObject.to_Description[0];
string formattedjson = JsonConvert.SerializeObject(changedObject);
Console.WriteLine(formattedjson);
}
Why not:
public class EntityDescription
{
public string ProductDescription { get; set; }
}
public class Entity
{
public string Product { get; set; }
}
public class Source : Entity
{
[JsonProperty("to_Description")]
public EntityDescription[] Description { get; set; }
}
public class Target : Entity
{
[JsonProperty("to_Description")]
public EntityDescription Description { get; set; }
}
var raw = File.ReadAllText(#"output.json");
var source = JsonConvert.DeserializeObject<Source>(raw);
var target = new Target { Product = source.Product, Description = source.Description.FirstOrDefault() };
var rawResult = JsonConvert.SerializeObject(target);
Update For dynamic JSON
var jObject = JObject.Parse(File.ReadAllText(#"output.json"));
var newjObject = new JObject();
foreach(var jToken in jObject) {
if(jToken.Value is JArray) {
List<JToken> l = jToken.Value.ToObject<List<JToken>>();
if(l != null && l.Count > 0) {
newjObject.Add(jToken.Key, l.First());
}
} else {
newjObject.Add(jToken.Key, jToken.Value);
}
}
var newTxt = newjObject.ToString();

How to issue GET request and parse result to list

Data contains place_id and other columns:
place_id name city address ..
133 place1 Laagri Born 12 ..
161 place2 Mourdi Karve 12 ..
Data is avaliable in 5 different formats. All those urls return same data:
http://www.smartpost.ee/places.html
http://www.smartpost.ee/places.xml
http://www.smartpost.ee/places.csv
http://www.smartpost.ee/places.js
http://www.smartpost.ee/places.php
One of urls should selected to get data. Data may change so it should not cached.
How to issue http GET requet and create two element List: first element is place_id from first column and second element is concatenated name, city and address field. Something like:
class DeliveryList {
public string Id, Address;
}
List<DeliveryList> res= GetAndParse("http://www.smartpost.ee/places.csv",
"place_id, name+\" \"+ city +\" \" + address" );
How to implement GetAndParse ? Should http request saved to sting and filehelpers used to parse it ? Expression "place_id, name+\" \"+ city +\" \" + address" can hard-coded in code instead of passing as parameter.
Using ASP.NET MVC4, .NET 4, C# . Code should run in MVC4 controller in server.
I suggest you to use XML endpoint and implement deserialization to array of places as implemented below:
public static class PlacesHelper
{
private const string EndpointUrl = "http://www.smartpost.ee/places.xml";
/// <summary> Load array of places </summary>
public static async Task<Places> LoadPlacesAsync()
{
var xmlString = await HttpRequestHelper.DownloadStringAsync(EndpointUrl);
return SerializationHelper.DeserializeXmlString<Places>(xmlString);
}
}
public static class SerializationHelper
{
/// <summary> Deserializes Xml string of type T. </summary>
public static T DeserializeXmlString<T>(string xmlString)
{
T tempObject = default(T);
using (var memoryStream = new MemoryStream(StringToUTF8ByteArray(xmlString)))
{
var xs = new XmlSerializer(typeof (T));
var xmlTextWriter = new XmlTextWriter(memoryStream, Encoding.UTF8);
tempObject = (T) xs.Deserialize(memoryStream);
}
return tempObject;
}
/// <summary> Convert String to Array </summary>
private static Byte[] StringToUTF8ByteArray(String xmlString)
{
return new UTF8Encoding().GetBytes(xmlString);
}
}
public static class HttpRequestHelper
{
/// <summary> Download String Async </summary>
public static async Task<string> DownloadStringAsync(string uri)
{
var client = new WebClient();
return await client.DownloadStringTaskAsync(uri);
}
}
[Serializable]
[XmlRoot("places_info", Namespace = "")]
public class Places
{
[XmlElement("place", typeof(Place), Form = XmlSchemaForm.Unqualified, IsNullable = false)]
public Place[] Place { get; set; }
}
[Serializable]
public class Place
{
[XmlElement("place_id")]
public string Id { get; set; }
[XmlElement("name")]
public string Name { get; set; }
[XmlElement("city")]
public string City { get; set; }
[XmlElement("address")]
public string Address { get; set; }
}
Usage:
var arrayOfPlaces = await PlacesHelper.LoadPlacesAsync();
So, you will get an array of places (id, name, city, address).
UPDATE:
For .NET Framework 4 Microsoft released the Async Targeting Pack (Microsoft.Bcl.Async) through Nuget. So Install the package 'Microsoft Async' from Nuget and you will be able to use async/await.
Example implementation of controller action:
public class TestController : Controller
{
public async Task<object> GetPlaces()
{
return Json(await PlacesHelper.LoadPlacesAsync(), JsonRequestBehavior.AllowGet);
}
}
I choose XML format to parse data, using XmlSerializer. Here is the code.
Classes represent our XML data: the code is self-explained
[XmlRoot("places_info")]
public class PlacesInfo
{
[XmlElement("place")]
public Place[] Places { get; set; }
}
public class Place
{
[XmlElement("place_id")]
public string Id { get; set; }
[XmlElement("name")]
public string Name { get; set; }
[XmlElement("city")]
public string City { get; set; }
[XmlElement("address")]
public string Address { get; set; }
}
Your Delivery class:
public class Delivery
{
public string Id { get; set; }
public string Address { get; set; }
public Delivery(string id, string address)
{
Id = id;
Address = address;
}
}
Code to get and parse data:
static void Main(string[] args)
{
// Get XML string from web
var client = new WebClient();
// Set encoding for non-ASCII characters
client.Encoding = Encoding.UTF8;
string xml = client.DownloadString("http://www.smartpost.ee/places.xml");
// Create a serializer
var serializer = new XmlSerializer(typeof(PlacesInfo));
// Variable to hold all XML data
PlacesInfo info;
// Deserialize XML string to object
using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(xml)))
{
info = (PlacesInfo) serializer.Deserialize(stream);
}
// Create delivery list
var deliveryList = new List<Delivery>();
// For each place
foreach (var place in info.Places)
{
// Concatenate name, city, and address
string address = string.Format("{0} {1} {2}", place.Name, place.City, place.Address);
// Add new delivery
var delivery = new Delivery(place.Id, address);
deliveryList.Add(delivery);
// Display to test
Console.WriteLine(delivery.Id + " " + delivery.Address);
}
Console.ReadLine();
}
I put comment in the code carefully. If you find something hard to understand, feel free to let me know. Hope this help :)

JavascriptSerializer, Deserializer, not able to deserialize my object

I am unable to deserialize my custom object.
public class UserInfo
{
public int Id1 { get; set; }
public string Code { get; set; }
public int Id2 { get; set; }
public List<string> Roles { get; set; }
public string Eg1 { get; set; }
public DateTime Time{ get; set; }
public string Eg2 { get; set; }
public string Version { get; set; }
}
JavaScriptSerializer serializer = new JavaScriptSerializer();
return serializer.Deserialize<UserInfo>(raw);
The Deserialize is throwing an exception
"Cannot convert object of type 'System.String' to type 'UserInfo'"
JSON Contents:
"\"{\\\"Id1\\\":0,\\\"Code\\\":null,\\\"Id2\\\":0,\\\"Roles\\\":null,\\\"Eg1\\\":\\\"Eg2\\\",\\\"Time\\\":\\\"\\\\/Date(-62135596800000)\\\\/\\\",\\\"Version\\\":\\\"1.0.0.0\\\"}\""
Note: Let me know, if it is unclear. I'll edit the question.
-- edited. ID2 changed to Id2. The real class is different in terms of variable names. Hence the issue.
Your string is a C# string containing a JavaScript string containing JSON. Short of fixing what you're being sent, here's how you would deserialize:
var jsonString = serializer.Deserialize<string>(raw);
return serializer.Deserialize<UserInfo>(jsonString);
You are passing a Javascript string to your deserializer because you have your object within an escaped string.
After unescaping it, this is what the serializer receives:
"{\"Id1\":0,\"Code\":null,\"Id2\":0,\"Roles\":null,\"Eg1\":\"Eg2\",\"Time\":\"\\/Date(-62135596800000)\\/\",\"Version\":\"1.0.0.0\"}"
What you really want to send it is:
{"Id1":0,"Code":null,"Id2":0,"Roles":null,"Eg1":"Eg2","Time":"\/Date(-62135596800000)\/","Version":"1.0.0.0"}"
Your ID2 is all caps in the JSON and the Id2 is not in your class.
EDIT:
Try creating an instance of the object and serialize it to JSON to compare and see if the JSON is correct or not. You can then use that string to properly format.
The code below should help someone get up and running.
the above code will cause an error on because string has no default constructor.
If a string is passed in from JSON.stringify() client JavaScript method the second Deserialize may work if the object passed in maps to the public fields in the object.
Let's look at a quick example presuming an .ASHX file receives the request from a jQuery call that looks like this:
//Called from with a jQuery ready() in a simple html page
var getNewPerson = function ()
{
var NewPerson = new Object();
NewPerson.PersonID = "0";
NewPerson.FirstName = $("#FirstName").val();
NewPerson.LastName = $("#LastName").val();
NewPerson.Address = $("#Address").val();
NewPerson.City = $("#City").val();
NewPerson.State = $("#State").val();
NewPerson.Zip = $("#Zip").val();
var arrObj;
var str = "";
var webMethod = "http://someserver.com/admin/DataHandler.ashx";
$.ajax({
cache: false,
url: webMethod,
type: "POST",
dataType: "json",
/* for hashtable or .net web service - data: "{\"NewPerson\":" + JSON.stringify(NewPerson) + "}", */
data: JSON.stringify(NewPerson),
contentType: "application/json; charset=utf-8"
}
)
.done( function(){}... code here ...etc)
//Valid JSON object format: {"PersonID":"1","FirstName":"Rick","LastName":"Wright","Address":"4520 No Such address Ave.","City":"Riverside","State":"CA","Zip":"92503"}
//And here is a sample class on the C# side in the .ashx handler page.
public class NewPerson
{
public int PersonID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Address { get; set; }
public string City { get; set; }
public string State { get; set; }
public string Zip { get; set; }
} // EOC Person
// And in the process request
public void ProcessRequest(HttpContext context)
{
string jsonString = "";
string rawJson = "";
System.Diagnostics.Debugger.Break();
HttpContext.Current.Request.InputStream.Position = 0;
string responseString;
var jsonSerializer = new JavaScriptSerializer();
/*Set the stream position to 0 */
context.Request.InputStream.Position = 0;
using (System.IO.StreamReader inputStream = new StreamReader(context.Request.InputStream))
{
rawJson = inputStream.ReadToEnd();
}
var objNewPerson = jsonSerializer.Deserialize<NewPerson>(rawJson);
if (clientList != null)
{
responseString = objNewPerson.FirstName + " " + objNewPerson.LastName ;
}
else
resp="No Record Found";
} // eof ProcessRequest

How to get JSON String value?

var responseFromServer =
// lines split for readability
"{\"flag\":true,\"message\":\"\",\"result\":{\"ServicePermission\":true,"
+ "\"UserGroupPermission\":true}}";
var serializer = new System.Web.Script.Serialization.JavaScriptSerializer();
var responseValue = serializer.DeserializeObject(responseFromServer);
responseFromServer value is get a webservice, and then how to get the JSON string value, such as "flag","Servicepermission"??
affix: i'm sorry, using c# to do this.
Note: The JavaScriptSerializer is actually the slowest JSON Serializer I've ever benchmarked. So much so I've had to remove it from my benchmarks because it was taking too long (>100x slower).
Anyway this easily solved using ServiceStack.Text's JSON Serializer:
var response = JsonSerializer.DeserializeFromString<Dictionary<string,string>>(responseFromServer);
var permissions = JsonSerializer.DeserializeFromString<Dictionary<string,string>>(response["result"]);
Console.WriteLine(response["flag"] + ":" + permissions["ServicePermission"]);
For completeness this would also work with ServiceStack.Text.JsonSerializer:
public class Response
{
public bool flag { get; set; }
public string message { get; set; }
public Permisions result { get; set; }
}
public class Permisions
{
public bool ServicePermission { get; set; }
public bool UserGroupPermission { get; set; }
}
var response = JsonSerializer.DeserializeFromString<Response>(responseFromServer);
Console.WriteLine(response.flag + ":" + response.result.ServicePermission);
if u are using jQuery u can do this
var json=jQuery.parseJSON(responseFromServer);
//acess
alert(json.ServicePermission);
if you are asing microsoft ajax do this
var json=Sys.Serialization.JavaScriptSerializer.deserialize(responseFromServer,true);
//acess
alert(json.ServicePermission);
in c# like php i have'nt seen any method that converts json to object on the fly. To do conversions in c# you must first create a class for this.
For your case you can do like this
//define classes
public class Response
{
public bool flag { get; set; }
public string message { get; set; }
public Permisions result { get; set; }
}
public class Permisions
{
public bool ServicePermission { get; set; }
public bool UserGroupPermission { get; set; }
}
var responseFromServer =
// lines split for readability
"{\"flag\":true,\"message\":\"\",\"result\":{\"ServicePermission\":true,"
+ "\"UserGroupPermission\":true}}";
var serializer = new System.Web.Script.Serialization.JavaScriptSerializer();
var responseValue = serializer.Deserialize<Response>(responseFromServer);
//access
responseValue.result.ServicePermission

Categories