{
Items: [
{
"title": "Object1",
"preview": {
"2048": "preview_9212.jpg",
"1024": "preview_6693.jpg",
}
},
{
"title": "Object2",
"preview": {
"2048": "preview_9888.jpg",
"1024": "preview_6890.jpg",
}
},
{
"title": "Object3",
"preview": {
"2048": "preview_9822.jpg",
"1024": "preview_6848.jpg",
}
}
]
}
I usually deserialise like this:
[Serializable]
public class JsonParser
{
public string title;
public List<Preview> preview;
}
[Serializable]
class Preview
{
public string 2048;
}
But since 2048 is an Integer is not possible to use this way.
I tried to deserialize the JSON to get preview like these:
public class Preview
{
[JsonProperty("2048")]
public string imageNumber { get; set; }
}
var user = JsonConvert.DeserializeObject<Preview>(jsonValue);
or
var json = JObject.Parse(jsonValue);
var preview = json["preview"].ToObject<Dictionary<string, string>>();
foreach (var entry in preview)
{
Debug.Log(entry.Key);
Debug.Log(entry.Value);
}
I got: NullReferenceException: Object reference not set to an instance of an object.
I also tried Deserializing JSON that has an int as a key in C# but again NullReferenceException;
Thanks for any help!
Since you have numeric string properties, you have 2 main choices:
Use something like [JsonProperty("2048")] and select valid name for the property
Or use a dictionary. This looks much more flexible for me, so you can try this code
Data data= JsonConvert.DeserializeObject<Data>(json);
string preview2048 = data.Items[0].Preview["2048"]; //preview_9212.jpg
or more complicated search using Linq
string obj3Preview2048 = data.Items.Where(i=> i.Title == "Object3")
.Select(i =>i.Preview["2048"]).FirstOrDefault(); //preview_9822.jpg
classes
public partial class Data
{
[JsonProperty("Items")]
public List<Item> Items { get; set; }
}
public partial class Item
{
[JsonProperty("title", NullValueHandling = NullValueHandling.Ignore)]
public string Title { get; set; }
[JsonProperty("token")]
public string Token { get; set; }
[JsonProperty("preview")]
public Dictionary<string, string> Preview { get; set; }
}
and you have some typos in json you posted, and I fix "type" to "title" in one of json objects. This is a fixed version
{
"Items": [{
"title": "Object1",
"token": "6561b1bbe5f1958848jhgd43d2",
"preview": {
"2048": "preview_9212.jpg",
"1024": "preview_6693.jpg"
}
},
{
"title": "Object2",
"token": "4a42eb54648DSFhUI664654d25",
"preview": {
"2048": "preview_9888.jpg",
"1024": "preview_6890.jpg"
}
},
{
"type": "Object3",
"token": "3fba64831dghkjgfkl5dfaegoj9",
"preview": {
"2048": "preview_9822.jpg",
"1024": "preview_6848.jpg"
}
}
]
}
Related
i have this API that i want to creat a dynamic object. My point here is to have normal object to deal with rather than what this API returns to me, i can't controll this API so the retrived data can't be modified, this is the body, and it represnet a view in Database
Also i think reflection could help me in this case, any idea....
Request Body:
{
"ViewName": "Person",
"ViewOutput": "Name, Email, Number",
"ViewFilter": [
{
"filterKey": "Number",
"filterValue": "532000000"
}
]
}
I want the ViewName + ViewOutput+ ViewFilter to be paramterized,
ViewName it will take single value,
ViewOutput will be array of string
ViewFilter will be list of filteration ("FilterKey", "FilterVlaue") because it could be mutliple filteration value like this:
"ViewFilter": [
{
"filterKey": "Number",
"filterValue": "532000000"
},
{
"filterKey": "Email",
"filterValue": "test1#test.ps"
}
]
This is What API Return to me, a list of Person Keys and values,
Response:
{
"ResponseCode": "0",
"ResponseMessage": "Success",
"NumberOfRecords": "1",
"MainData": [
{
"recordData": [
{
"dataKey": "Name",
"dataValue": "Test Name"
},
{
"dataKey": "Email",
"dataValue": "test#test.ps"
},
{
"dataKey": "Number",
"dataValue": "532000000"
}
]
}
]
}
What i want to be the output is like this:
"Person": [
{
"Name":"Test",
"Email":"test#test.ps",
"Number":"532000000",
}]
Pasting the response JSON into an empty class file in Visual Studio using the Paste JSON As Classes feature, yields these classes:
public class Rootobject
{
public string ResponseCode { get; set; }
public string ResponseMessage { get; set; }
public string NumberOfRecords { get; set; }
public Maindata[] MainData { get; set; }
}
public class Maindata
{
public Recorddata[] recordData { get; set; }
}
public class Recorddata
{
public string dataKey { get; set; }
public string dataValue { get; set; }
}
You can create your own Person class.
Once you deserialize the JSON into the generated classes, one way to get a List<Person> would be to do something like this (please note that this is untested example code):
var people = rootObject.Maindata.Select(r =>
{
var name = r.recordData.Single(d => d.dataKey == "Name").dataValue;
var email = r.recordData.Single(d => d.dataKey == "Email").dataValue;
var number = r.recordData.Single(d => d.dataKey == "Number").dataValue;
return new Person(name, email, number);
}).ToList();
Hi I having following JSON but while Using Deserialize method getting NULL in nested Member here is the sample JSON and corresponding Class object:
{
"status": "success",
"Info": [
{
"Name": "1099589",
"version": "Current Version",
"MoreDetails": [
{
"Name": "1099589",
"state": "IN"
},
{
"Name": "1099768",
"state": "OUT"
}
]
},
{
"Name": "1099768",
"version": "2019"
}
],
"errorCode": "",
"message": ""
}
Class :
public class MoreDetail
{
public string Name { get; set; }
public string state { get; set; }
}
public class Info
{
public string Name { get; set; }
public string version { get; set; }
public IList<MoreDetail> MoreDetails { get; set; }
}
public class Example
{
public string status { get; set; }
public IList<Info> Info { get; set; }
public string errorCode { get; set; }
public string message { get; set; }
}
While I am using
JavaScriptSerializer js = new JavaScriptSerializer();
Example ex = new OfferingPayload();
ex = js.Deserialize<Example> (jsonstring);
I am able to see Example object having Info data as list but MoreDetails member of Info Class is coming NULL.
Can someone suggest what I am missing here ?
Thats because your second "Info" object doesnt have "MoreDetails" property.
{
"Name": "1099768",
"version": "2019"
}
To make it works you can add an empty "MoreDetails" property to your json.
{
"Name": "1099768",
"version": "2019",
"MoreDetails": []
}
Or you can configure your serializer to handle this property as optional. Then it will works fine even if it missing in your json.
I have stored JSON data in a string and by using the JObject, I am trying to get values from JSON data. I am just not able to figure out that what is the underlying issue with my code because I am not able to get data from the JSON object. A snippet of my code is attached below. If some can help me out to figure out the issue it will be immensely appreciated.
String text;
try {
var response = (HttpWebResponse)request.GetResponse();
using (var sr = new StreamReader(response.GetResponseStream()))
{
text = sr.ReadToEnd();
JObject jObject = JObject.Parse(text);
string haha = (string)jObject["value/segments/requests/count/sum"];
ViewBag.gotstring = haha;
}
System.Diagnostics.Debug.WriteLine(text);
} catch(Exception e) {
System.Diagnostics.Debug.WriteLine(url);
System.Diagnostics.Debug.WriteLine(e.ToString()); }
return View();
Here is the JSON:
{
"value": {
"start": "2018-08-12T04:44:38.941Z",
"end": "2018-08-12T16:44:38.941Z",
"interval": "PT30M",
"segments": [
{
"start": "2018-08-12T14:00:00Z",
"end": "2018-08-12T14:30:00Z",
"segments": [
{
"requests/count": {
"sum": 2
},
"request/name": "GET Home/Index"
},
{
"requests/count": {
"sum": 1
},
"request/name": "GET Home/About"
},
{
"requests/count": {
"sum": 1
},
"request/name": "GET Home/Contact"
}
]
},
{
"start": "2018-08-12T14:30:00Z",
"end": "2018-08-12T15:00:00Z",
"segments": [
{
"requests/count": {
"sum": 2
},
"request/name": "GET Account/Register"
},
{
"requests/count": {
"sum": 1
},
"request/name": "GET Account/Login"
}
]
},
{
"start": "2018-08-12T15:30:00Z",
"end": "2018-08-12T16:00:00Z",
"segments": [
{
"requests/count": {
"sum": 8
},
"request/name": "GET Home/Index"
},
{
"requests/count": {
"sum": 8
},
"request/name": "GET Home/About"
}
]
}
]
}
}
jObject does not work this way. It returns dictionary that you can query by key, but keys are single level. I.e. you'll be able to get some data like this:
var haha = jObject["value"]["segments"];
But beyond that it gets very complex. You'll be much better off defining a C# class that represents your JSON and serialise into that. A simple `Edit=>Paste Special => JSON as Class" in Visual Studio gives this:
public class Rootobject
{
public Value value { get; set; }
}
public class Value
{
public DateTime start { get; set; }
public DateTime end { get; set; }
public string interval { get; set; }
public Segment[] segments { get; set; }
}
public class Segment
{
public DateTime start { get; set; }
public DateTime end { get; set; }
public Segment1[] segments { get; set; }
}
public class Segment1
{
[JsonProperty("requests/count")]
public RequestsCount requestscount { get; set; }
[JsonProperty("request/name")]
public string requestname { get; set; }
}
public class RequestsCount
{
public int sum { get; set; }
}
and then deserialise like this:
var serialised = JsonConvert.DeserializeObject<Rootobject>(json);
var haha = serialised.value.segments.FirstOrDefault().segments.FirstOrDefault().requestscount.sum;
And here is a working sample: https://dotnetfiddle.net/CZgMNE
Can you try:
EDIT: seems like segments is an array, this will get you the sum for first segment only
string haha = (string)jObject["value"]["segments"][0]["segments"]["requests/count"]["sum"];
public static string DeserializeNames()
{
// Json I am passing for the deserialization.
JsonStream= "{
"head": {
"Rows": [
"test 1",
[
[
{
"#Key": "Domain",
"#value": "LocalHost"
},
{
"#Key": "Cookie name(s)",
"#value": "Google"
},
{
"#Key": "Purpose",
"#value": "Test"
},
{
"#Key": "lifetime",
"#value": "test"
}
]
]
]
}
}"
//deserialize JSON from file
JavaScriptSerializer serializer = new JavaScriptSerializer();
var cookieList = serializer.Deserialize<List<Cookie>>(JsonStream).ToList();
}
//Class descriptions
//I have created below classes for the deserialization. Records are not deserialized i am getting zero record count.
public class Categorization
{
public string categorizationName { get; set; }
public List<object> KeyValue{ get; set; }
}
public class Head
{
public IList<Categorization> Rows { get; set; }
}
public class Cookie
{
public Head head { get; set; }
}
Also created below set of the classes and tried the deserialization, Still no luck
public class Head
{
public List<object> Rows { get; set; }
}
public class Cookie
{
public Head head { get; set; }
}
I am getting count as 0 i am not able to fetch any record.
Please help !!
I have modified the Json as below and stored in in the file "test.json" :
{
"head": {
"TestRows": [
[
{
"Key": "Domain",
"value": "Google"
},
{
"Key": "Cookie",
"value": "Test"
},
{
"Key": "Use for",
"value": "Test."
},
{
"Key": "Expire Time",
"value": "1 hour"
}
]
]
}
}
And created below set of classes :
public class Head
{
public IList<List<Dictionary<string, object>>> TestRows{ get; set; }
}
public class Cookie
{
public Head Head { get; set; }
}
var baseDirectory = AppDomain.CurrentDomain.BaseDirectory;
var path= Path.Combine(baseDirectory, "test.json");
//deserialize JSON from file
string JsonStream = System.IO.File.ReadAllText(path, Encoding.Default);
var DeserializedCookieList = JsonConvert.DeserializeObject<Cookie>(JsonStream);
Deserialization is working properly.
I am using System.Net.Http.HttpClient, the version currently available in NuGet,
to retrieve data from a service in json format. The data roughly looks like this:
{
"schema": "Listing",
"data": {
"key": "28ba648c-de24-45d4-a7d9-70f810cf5438",
"children": [{
"kind": "type1",
"data": {
"body": "Four score and seven years ago...",
"parent_id": "2qh3l",
"report_count": 0,
"name": "c4j6yeh"
}
}, {
"kind": "type3",
"data": {
"domain": "abc.def.com",
"flagged": true,
"category": "news",
"saved": false,
"id": "t3dz0",
"created": 1335998011.0
}
}]
}
}
I use HttpContentExtensions.ReadAsAsync<T> to de-serialize that json string into an object graph. The type definitions looks roughly like this:
public class Response
{
public String schema { get;set; }
public ListingData data { get;set; }
}
public class ListingData
{
public string key { get;set; }
public List<OneItem> children { get;set; }
}
Here's the problem: I desire the type of the items in children to vary depending on the kind property. If kind is "type1" then I want to de-serialize an object of... let's call it Type1 . If kind is "type3" then I want an object of type Type3.
Right now, I can deserialize a List<Type1> or a List<Type3>, but I don't know how to tell the de-serialization logic to distinguish between the two.
I could merge all the properties of the "type1" data object and the "type3" data object into a single .NET Type. But the number of properties is large enough that this gets messy.
If the name of the property in the JSON (in this case data) were different, I could distinguish using that. If, for example, the data looked like this:
"children": [{
"kind": "type1",
"t1data": { ... }
}, {
"kind": "type3",
"t3data": { ... }
}]
...then I could do something like this in .NET:
public class OneItem
{
public string kind { get;set; }
public Type1 t1data { get;set; }
public Type3 t3data { get;set; }
}
But my data schema doesn't look like that.
Is it possible to choose the type for de-serialization by the content of the data? In other words,
look at the value of one property (in this case, kind) to determine how to de-serialize the content for another property (in this case, data).
Or is it possible to inject a filter or transformer that acts on the JSON before ReadAsAsync tries to deserialize it?
If so, How?
If you're ok w/ doing some pre-processing on your response and you can use Json.NET, you should be able to do what you want.
Given the following classes:
public class Response
{
public string schema
{
get;
set;
}
public ListingData data
{
get;
set;
}
}
public class ListingData
{
public string key
{
get;
set;
}
public List<object> children
{
get;
set;
}
}
public class Type1
{
public string body
{
get;
set;
}
public string parent_id
{
get;
set;
}
public int report_count
{
get;
set;
}
public string name
{
get;
set;
}
}
public class Type3
{
public string domain
{
get;
set;
}
public bool flagged
{
get;
set;
}
public string category
{
get;
set;
}
public bool saved
{
get;
set;
}
public string id
{
get;
set;
}
public double created
{
get;
set;
}
}
This test passes:
[Test]
public void RoundTrip()
{
var response = new Response
{
schema = "Listing",
data = new ListingData
{
key = "28ba648c-de24-45d4-a7d9-70f810cf5438",
children = new List<object>
{
new Type1
{
body = "Four score and seven years ago...",
parent_id = "2qh3l",
report_count = 0,
name = "c4j6yeh"
},
new Type3
{
domain = "abc.def.com",
flagged = true,
category = "news",
saved = false,
id = "t3dz0",
created = 1335998011.0
}
}
}
};
var jsonSerializerSettings = new JsonSerializerSettings
{
Formatting = Formatting.Indented,
TypeNameHandling = TypeNameHandling.Objects
};
string serializedResponse = JsonConvert.SerializeObject(response, jsonSerializerSettings);
Console.WriteLine(serializedResponse);
var roundTrippedResponse = JsonConvert.DeserializeObject<Response>(serializedResponse, jsonSerializerSettings);
Assert.That(roundTrippedResponse.data.children.First().GetType(), Is.EqualTo(typeof(Type1)));
Assert.That(roundTrippedResponse.data.children.Last().GetType(), Is.EqualTo(typeof(Type3)));
}
The output written to the console is:
{
"$type": "Test.Response, Test",
"schema": "Listing",
"data": {
"$type": "Test.ListingData, Test",
"key": "28ba648c-de24-45d4-a7d9-70f810cf5438",
"children": [
{
"$type": "Test.Type1, Test",
"body": "Four score and seven years ago...",
"parent_id": "2qh3l",
"report_count": 0,
"name": "c4j6yeh"
},
{
"$type": "Test.Type3, Test",
"domain": "abc.def.com",
"flagged": true,
"category": "news",
"saved": false,
"id": "t3dz0",
"created": 1335998011.0
}
]
}
}
So if you can transform your received response to match that of Json.NET's expected format, this will work.
To piece all of this together, you would need to write a custom MediaTypeFormatter and pass it to the ReadAsAsync<>() call.