Deserialise JSON To Generic Type Object - c#

I have some JSON that looks like this:
{
"data": {
"storePurchase": {
"id": "d4f7475a-0023-416f-b6a1-257659a341f5",
}
}
}
I also have some JSON that looks like this:
{
"data": {
"userInfo": {
"username": "...."
}
}
}
How can I write a deserializer to handle any object type that might appear under data. I know the structure of the sub-objects under data upfront, so I don't need dynamics.
I have tried this so far:
public class BaseData<T>
{
public T Data { get; set; }
}
[JsonObject("userInfo")]
public class Me
{
[JsonProperty("username")]
public string Username { get; set; }
}
public class BootstrapQueryResponse
{
[JsonProperty("data")]
public BaseData<Me> BaseData { get; set; }
}
[TestMethod]
public void Test()
{
string json = #"{
""data"": {
""userInfo"": {
""username"": ""....""
}
}
}";
BootstrapQueryResponse s = JsonConvert.DeserializeObject<BootstrapQueryResponse>(json);
}
However, my object s is returning null for the data property.

#dbc is right, try:
public class BaseData<T>
{
[JsonProperty("data")] // <-- this goes here
public T Data { get; set; }
}
var s = JsonConvert.DeserializeObject<BaseData<Me>>(json)

Related

I can't deserialize the JSON

I'm trying to connect to the PostNL API Timeframes. The problem is that I keep getting the following exception. I think I got my models correctly but I can't seem to find out what's wrong with it.
Exception:
Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'System.Collections.Generic.List`1[PostNL.Api.Dtos.TimeFrameHolderDto]' because the type requires a JSON array (e.g. [1,2,3]) to deserialize correctly.
To fix this error either change the JSON to a JSON array (e.g. [1,2,3]) or change the deserialized type so that it is a normal .NET type (e.g. not a primitive type like integer, not a collection type like an array or List) that can be deserialized from a JSON object. JsonObjectAttribute can also be added to the type to force it to deserialize from a JSON object.
Path 'Timeframes.Timeframe', line 3, position 16.
at PostNL.Api.Tests.Unit.Tests.Unit.TimeFramesTests.TimeFrameResponseJsonTests.JsonConvertTests(String filePath) in C:\Git\PostNL.Api.Tests.Unit\TimeFramesTests\TimeFrameResponseJsonTests.cs:line 37
If I read the error I need to create some more models with holders and lists like I did as below but I'm still getting this exception. Does anyone know what I'm doing wrong?
requests/1.json file:
{
"Timeframes": {
"Timeframe": [
{
"Date": "22-08-2022",
"Timeframes": {
"TimeframeTimeFrame": [
{
"From": "08:45:00",
"Options": {
"string": "Daytime"
},
"To": "11:15:00"
},
{
"From": "17:30:00",
"Options": {
"string": "Evening"
},
"To": "22:00:00"
}
]
}
},
{
"Date": "23-08-2022",
"Timeframes": {
"TimeframeTimeFrame": [
{
"From": "09:15:00",
"Options": {
"string": "Daytime"
},
"To": "11:45:00"
},
{
"From": "17:30:00",
"Options": {
"string": "Evening"
},
"To": "22:00:00"
}
]
}
}
]
}
}
The deserialization test:
using PostNL.Api.Dtos;
using Newtonsoft.Json;
using NUnit.Framework;
using System;
using System.IO;
namespace PostNL.Api.Tests.Unit.TimeFramesTests
{
[TestFixture]
[Parallelizable(ParallelScope.All)]
internal class TimeFrameResponseJsonTests
{
[Test]
[TestCase("../../../TimeFramesTests/requests/1.json")]
public void JsonConvertTests(string filePath)
{
var path = AppDomain.CurrentDomain.BaseDirectory;
var fullFilePath = Path.Combine(path, filePath);
if (!File.Exists(fullFilePath))
{
Assert.Fail("File does not exists");
return;
}
try
{
var fileContent = File.ReadAllText(filePath);
var json = JsonConvert.DeserializeObject<TimeFrameResponseDto>(fileContent);
}
catch (Exception exception)
{
Assert.Fail(exception.Message);
}
Assert.Pass("Successful convert");
}
}
}
The models:
using Newtonsoft.Json;
using System.Collections.Generic;
namespace PostNL.Api.Dtos
{
internal class TimeFrameDto
{
[JsonProperty("From")]
public string From { get; set; }
[JsonProperty("Options")]
public OptionDto[] Options { get; set; }
[JsonProperty("To")]
public string To { get; set; }
}
internal class TimeFrameTimeFrameHolder
{
[JsonProperty("TimeframeTimeFrame")]
public List<TimeFrameDto> TimeFrameTimeFrame { get; set; }
}
internal class DayTimeFrameDto
{
[JsonProperty("Date")]
public string Date { get; set; }
[JsonProperty("Timeframes")]
public List<TimeFrameTimeFrameHolder> TimeFrameDtos { get; set; }
}
internal class TimeFrameHolderDto
{
[JsonProperty("Timeframe")]
public List<DayTimeFrameDto> TimeFrames { get; set; }
}
internal class TimeFrameResponseDto : PostNLBaseDto
{
[JsonProperty("Timeframes")]
public List<TimeFrameHolderDto> TimeFrames { get; set; }
//[JsonProperty("ReasonNoTimeframes")]
//public List<ReasonNoTimeFrameDto> ReasonNoTimeFrames { get; set; }
}
}
you need one more class - DataTimeframesDto
TimeFramesResponseDTo timeFramesResponseDTo=JsonConvert.DeserializeObject<TimeFramesResponseDTo>(fileContent);
public partial class TimeFramesResponseDTo
{
[JsonProperty("Timeframes")]
public DataTimeframesDto Timeframes { get; set; }
}
public partial class DataTimeframesDto
{
[JsonProperty("Timeframe")]
public List<DayTimeFrameDto> Timeframe { get; set; }
}
UPDATE
The rest of my classes it you still can't use yours
public partial class DayTimeFrameDto
{
[JsonProperty("Date")]
public string Date { get; set; }
[JsonProperty("Timeframes")]
public TimeFrameTimeFrameHolder Timeframes { get; set; }
}
public partial class TimeFrameTimeFrameHolder
{
[JsonProperty("TimeframeTimeFrame")]
public List<TimeframeDTo> TimeFrameTimeFrame{ get; set; }
}
public partial class TimeframeDTo
{
[JsonProperty("From")]
public DateTime From { get; set; }
[JsonProperty("Options")]
public OptionsDto Options { get; set; }
[JsonProperty("To")]
public DateTime To { get; set; }
}
public partial class OptionsDto
{
[JsonProperty("string")]
public string OptionsString { get; set; }
}

Parse (Deserialize) JSON with dynamic keys (C#)

I want to parse the JSON on the bottom. Till now I always have the static key for the variables, but in this example, the keys are always changing. Here the "58e7a898dae4c" and "591ab00722c9f" could have any value and change constantly. How can I get the value of the elements of the set to be able to reach the PreviewName value?
{
"key": "gun",
"objects": [
{
"name": "AK47",
"sets": {
"58e7a898dae4c": {
"set_id": "58e75660719a9f513d807c3a",
"preview": {
"resource": {
"preview_name": "preview.040914"
}
}
},
"591ab00722c9f": {
"set_id": "58eba618719a9fa36f881403",
"preview": {
"resource": {
"preview_name": "preview.81a54c"
}
}
}
}
}
]
}
public class Object
{
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("sets")]
public Dictionary<string, Set> Sets { get; set; }
}
public class Set
{
[JsonProperty("set_id")]
public string SetId { get; set; }
[JsonProperty("preview")]
public Preview Preview { get; set; }
}
public class Preview
{
[JsonProperty("resource")]
public ResourcePreview Resource { get; set; }
}
public class ResourcePreview
{
[JsonProperty("preview_name")]
public string PreviewName { get; set; }
}
var root = JsonConvert.DeserializeObject<RootObject>(json);
string previewName1 = root.Objects[0].Sets["58e7a898dae4c"].Preview.Resource.PreviewName;
string previewName2 = root.Objects[0].Sets["591ab00722c9f"].Preview.Resource.PreviewName;
you don't need to deserialize, you can parse
var jsonParsed=JObject.Parse(json);
string[] previewNames= ((JArray)jsonParsed["objects"])
.Select(v => ((JObject)v["sets"]))
.Select(i=>i.Properties().Select(y=> y.Value["preview"]["resource"])).First()
.Select(i=> (string) ((JObject)i)["preview_name"]).ToArray();
result
preview.040914
preview.81a54c

How to get inner field's value of object by using JsonProperty

I have data in json like this:
{
"data": {
"name" : "Car wash"
"changed_by": {
"id": 1,
"name": "Pascal",
"type": "user"
}
}
}
The value "Car wash" I can get like this:
public class Changes
{
[JsonProperty("name")]
public string name { get; set; }
}
How I can get the value of some changed_by object field?
I need to use this in deserializing
private void GetChanges(RawData data)
{
var changes = JsonConvert.DeserializeObject<Response<IEnumerable<Model.Json.Changes>>>(data.ChangesData);
/* some code */
}
You just need to have a class that represents the changed_by object. For example:
public class Data
{
public string name { get; set; }
public ChangedBy changed_by { get; set; }
}
public class ChangedBy
{
public int id { get; set; }
public string name { get; set; }
public string type { get; set; }
}
Create a class hierarchy representing the structure of the data in and then use Json.Net to deserialize it into an object of this class.
Check out Json.Net

Deserialize JSON object with unknown name

I have json like this
{
"result": "success",
"response_code": 200,
"message": "",
"collection": {
"<channel_id>": {
"<category_id>": {
"id_category": "<category_id>",
"name": "<category>",
"date_created": "<date_tagged>"
},
"<category_id>": {
"id_category": "<category_id>",
"name": "<category>",
"date_created": "<date_tagged>"
}
}
}
}
which channel_id and category_id is not a fixed name. How do I can deserialize it on C#?
Assuming everything else is pretty much fixed, you might try to model this along these lines:
public class MyJsonClass
{
public String Result { get; set; }
public int Response_Code { get; set; }
public String Message { get; set; }
public Dictionary<String, Dictionary<String, JsonCategoryDescription>>
Collection { get; set; }
}
public class JsonCategoryDescription
{
public String Id_Category { get; set; }
public String Name { get; set; }
public String Date_Created { get; set; }
}
Then you deserialize it as follows (System.Web.Script.Serialization namespace):
var result = new JavaScriptSerializer().Deserialize<MyJsonClass>(myJsonString);
and you can access specific fields, like so:
result.Collection[SOME_CHANNEL_ID][SOME_CATEGORY_ID].Name = "XXX";
If you use Dynamic instead of a static type you can have a variable schema of your JSON file. Here is a working console program:
class Program
{
static void Main(string[] args)
{
var json = File.ReadAllText("file.json");
dynamic obj = JObject.Parse(json);
Console.WriteLine(obj.collection.channel_id);
}
}

RestSharp JSON Array deserialization

I launch this RestSharp query in JSON format:
var response = restClient.Execute<Report>(request);
The response I get contains this data
[
{
"Columns":
[
{"Name":"CameraGuid","Type":"Guid"},
{"Name":"ArchiveSourceGuid","Type":"Guid"},
{"Name":"StartTime","Type":"DateTime"},
{"Name":"EndTime","Type":"DateTime"},
{"Name":"TimeZone","Type":"String"},
{"Name":"Capabilities","Type":"UInt32"}
],
"Rows":
[
[
"00000001-0000-babe-0000-00408c71be50",
"3782fe37-6748-4d36-b258-49ed6a79cd6d",
"2013-11-27T17:52:00Z",
"2013-11-27T18:20:55.063Z",
"Eastern Standard Time",
2147483647
]
]
}
]
I'm trying to deserialize it into this group of classes:
public class Report
{
public List<ReportResult> Results { get; set; }
}
public class ReportResult
{
public List<ColumnField> Columns { get; set; }
public List<RowResult> Rows { get; set; }
}
public class ColumnField
{
public string Name { get; set; }
public string Type { get; set; }
}
public class RowResult
{
public List<string> Elements { get; set; }
}
Unfortunately, the result data is null and I get this exception:
Unable to cast object of type 'RestSharp.JsonArray' to type
'System.Collections.Generic.IDictionary`2[System.String,System.Object]'.
I cannot figure out what is wrong here.
I little help would be greatly appreciated.
Try this:
var response = restClient.Execute<List<ReportResult>>(request);
EDIT
You should also change ReportResult to:
public class ReportResult
{
public List<ColumnField> Columns { get; set; }
public List<List<string>> Rows { get; set; }
}
and you can get rid of Report and RowResult.
There is another way by creating wrapper class:
public class ThirdPartySuggesters : List<ThirdPartySuggester> {}
var response = client.Execute<ThirdPartySuggesters>(request);

Categories