C# Parse JSON response (Get a specific part from response) - c#

I am trying to get a specific part from a JSON response string.
Here is the JSON code :
{
"metadata": {
"provider": "Oxford University Press"
},
"results": [
{
"id": "door",
"language": "en",
"lexicalEntries": [
{
"entries": [
{
"homographNumber": "000",
"senses": [
{
"definitions": [
"a hinged, sliding, or revolving barrier at the entrance to a building, room, or vehicle, or in the framework of a cupboard"
],
"id": "m_en_gbus0290920.005",
"subsenses": [
{
"definitions": [
"a doorway"
],
"id": "m_en_gbus0290920.008"
},
{
"definitions": [
"used to refer to the distance from one building in a row to another"
],
"id": "m_en_gbus0290920.009"
}
]
}
]
}
],
"language": "en",
"lexicalCategory": "Noun",
"text": "door"
}
],
"type": "headword",
"word": "door"
}
]
}
I am trying to get this code
"definitions": [
"a hinged, sliding, or revolving barrier at the entrance to a building, room, or vehicle, or in the framework of a cupboard"
in a string
Here is my code:
string language = "en";
string word_id = textBox1.Text.ToLower();
String url = "https://od-api.oxforddictionaries.com:443/api/v1/entries/" + language + "/" + word_id+"/definitions";
HttpClient client = new HttpClient();
client.BaseAddress = new Uri(url);
client.DefaultRequestHeaders.Add("app_id", app_Id);
client.DefaultRequestHeaders.Add("app_key", app_Key);
HttpResponseMessage response = client.GetAsync(url).Result;
if (response.IsSuccessStatusCode)
{
var result = response.Content.ReadAsStringAsync().Result;
var s = JsonConvert.DeserializeObject(result);
textBox2.Text = s.ToString();
}
else MessageBox.Show(response.ToString());
I am using C#.

C# Classes
Step one is to create some classes to allow us to represent the data in C#. If you don't have them... QuickType does that.
namespace QuickType
{
using System;
using System.Net;
using System.Collections.Generic;
using Newtonsoft.Json;
public partial class GettingStarted
{
[JsonProperty("metadata")]
public Metadata Metadata { get; set; }
[JsonProperty("results")]
public Result[] Results { get; set; }
}
public partial class Result
{
[JsonProperty("id")]
public string Id { get; set; }
[JsonProperty("language")]
public string Language { get; set; }
[JsonProperty("lexicalEntries")]
public LexicalEntry[] LexicalEntries { get; set; }
[JsonProperty("type")]
public string Type { get; set; }
[JsonProperty("word")]
public string Word { get; set; }
}
public partial class LexicalEntry
{
[JsonProperty("entries")]
public Entry[] Entries { get; set; }
[JsonProperty("language")]
public string Language { get; set; }
[JsonProperty("lexicalCategory")]
public string LexicalCategory { get; set; }
[JsonProperty("text")]
public string Text { get; set; }
}
public partial class Entry
{
[JsonProperty("homographNumber")]
public string HomographNumber { get; set; }
[JsonProperty("senses")]
public Sense[] Senses { get; set; }
}
public partial class Sense
{
[JsonProperty("definitions")]
public string[] Definitions { get; set; }
[JsonProperty("id")]
public string Id { get; set; }
[JsonProperty("subsenses")]
public Subsense[] Subsenses { get; set; }
}
public partial class Subsense
{
[JsonProperty("definitions")]
public string[] Definitions { get; set; }
[JsonProperty("id")]
public string Id { get; set; }
}
public partial class Metadata
{
[JsonProperty("provider")]
public string Provider { get; set; }
}
public partial class GettingStarted
{
public static GettingStarted FromJson(string json) => JsonConvert.DeserializeObject<GettingStarted>(json, Converter.Settings);
}
public static class Serialize
{
public static string ToJson(this GettingStarted self) => JsonConvert.SerializeObject(self, Converter.Settings);
}
public class Converter
{
public static readonly JsonSerializerSettings Settings = new JsonSerializerSettings
{
MetadataPropertyHandling = MetadataPropertyHandling.Ignore,
DateParseHandling = DateParseHandling.None,
};
}
}
Deserialize
You'll notice that we also have converters to serialize and deserialize generated for us. The deserialize bit is as simple as:
var result = JsonConvert.DeserializeObject<GettingStarted>(json);
Use
Start from the result variable and use dots to find your way down to your item...
var description = result.results.lexicalEntries.First()
.entries.First()
.senses.First()
.definitions.First();
All of those First() calls are due to each of these parts of the data being arrays. You'll need to reference System.Linq for that. You will want to read a little around what to do if you have more than one, or less than one, at any of those levels (you may need to work with collections, or perform more traversal).

You can create a class whose properties are the names of the JSON you are trying to parse. That way you can deserialize the JSON into an instance of that class and pull whatever property you need. You'll need to use the Newtonsoft.Json package.
Example class:
public class YourClass
{
public string propertyA { get; set; }
public string propertyB { get; set; }
}
And then in your main code:
YourClass yourClass = new YourClass();
try
{
yourClass = JsonConvert.DeserializeObject<YourClass>(yourJsonStringGoesHere);
}
catch (Exception ex)
{
//log exception here
}

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; }
}

Cannot serialize object from JSON using Unity's JsonUtilty when the object contains more objects

So I have an API set up that returns a JSON. The response looks as follows:
{
"success": true,
"results": 1,
"data": [
{
"location": {
"type": "Point",
"coordinates": [
-83.338322,
42.705647
],
"formattedAddress": "Some adress",
"city": "SomeCity",
"state": "STATE",
"zipcode": "000000",
"country": "US"
},
"_id": "630ce2c5a963f97ddae7387f",
"title": "Node Developer",
"description": "Must be a full-stack developer, able to implement everything in a MEAN or MERN stack paradigm (MongoDB, Express, Angular and/or React, and Node.js).",
"email": "employer#gmail.com",
"address": "someADress",
"company": "Company Ltd",
"industry": [
"Information Technology"
],
"jobType": "Permanent",
"minEducation": "Bachelors",
"positions": 2,
"experience": "No Experience",
"salary": 155000,
"lastDate": "2022-09-05T15:41:44.912Z",
"user": "630cdf34b2bc6356a75ec29c",
"postingDate": "2022-08-29T16:01:09.707Z",
"slug": "node-developer"
}
] }
And I am trying to serialize it as an object in C# using the following code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking;
public class test : MonoBehaviour
{
public string domain = "http://localhost:3000/api/v1";
public string request = "/jobs";
private bool coroutineRunning = false;
Request req;
private void Start()
{
req = new Request();
}
void Update()
{
if (Input.GetKeyDown(KeyCode.Space) && !coroutineRunning)
{
StartCoroutine(GetRequest(domain + request));
}
}
IEnumerator GetRequest(string uri)
{
coroutineRunning = true;
UnityWebRequest request = UnityWebRequest.Get(uri);
yield return request.SendWebRequest();
if (request.result == UnityWebRequest.Result.Success)
{
string jsonText = request.downloadHandler.text;
Debug.Log(jsonText);
SetUpObject(jsonText);
}
else
{
Debug.LogError(request.result);
}
coroutineRunning = false;
}
void SetUpObject(string json)
{
req = JsonUtility.FromJson<Request>(json);
Debug.Log(JsonUtility.ToJson(req, true));
Debug.Log(req);
}
}
The Request class:
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[Serializable]
public class Data
{
public Location location { get; set; }
public string _id { get; set; }
public string title { get; set; }
public string description { get; set; }
public string email { get; set; }
public string address { get; set; }
public string company { get; set; }
public string[] industry { get; set; }
public string jobType { get; set; }
public string minEducation { get; set; }
public int positions { get; set; }
public string experience { get; set; }
public int salary { get; set; }
public DateTime lastDate { get; set; }
public string user { get; set; }
public DateTime postingDate { get; set; }
public string slug { get; set; }
}
[Serializable]
public class Location
{
public string type { get; set; }
public double[] coordinates { get; set; }
public string formattedAddress { get; set; }
public string city { get; set; }
public string state { get; set; }
public string zipcode { get; set; }
public string country { get; set; }
}
[Serializable]
public class Request
{
public bool success { get; set; }
public int results { get; set; }
public Data[] data { get; set; }
}
The problem is that I can't figure out how I should create a class that can get serialized with this JSON. This API is from a course I took on creating API's and won't be used in a project, I am just trying to figure out how to properly use serialization with complex JSONs such as this one.
The request returns a string that is the JSON written above. I used that JSON format and JSON2CSHARP to generate the Request class (i know it should be called the result class). Now when I copied the generated class I swapped every List<T> with an array of that type. I also think that using Datetime instead of string and other type mismatches could be the source of the problem, but even if they were the JsonUtilty would've still populated the Success and Results fields of the Request class and left the Data as an empty array
From the Unity documentation, I see the following (emphasis added):
Fields of the object must have types supported by the serializer. Fields that have unsupported types, as well as private fields or fields marked with the NonSerialized attribute, will be ignored.
Based on that description, and the example provided, it looks like it may only work with fields and not properties. I would try to make everything a member variable instead of a property and see if that fixes it.
You don't need to remove setters, just download and install Newtonsoft.Json for Unity3d
using Newtonsoft.Json;
Request req = JsonConvert.DeserializeObject<Request>(json);

Loading JSON file gives serialization error

I have below JSON file,
[
{
"applicationConfig": {
"Name": "Name1",
"Site": "Site1"
},
"pathConfig": {
"SourcePath": "C:\\Temp\\Outgoing1",
"TargetPath": "C:\\Files"
},
"credentialConfig": {
"Username": "test1",
"password": "super1"
}
},
{
"applicationConfig": {
"Name": "Name2",
"Site": "Site2"
},
"pathConfig": {
"SourcePath": "C:\\Temp\\Outgoing2",
"TargetPath": "C:\\Files"
},
"credentialConfig": {
"Username": "test2",
"password": "super2"
}
}
]
And below are C# classes structure,
public class Configurations
{
public List<ApplicationConfig> ApplicationConfigs { get; set; }
public List<PathConfig> PathConfigs { get; set; }
public List<CredentialConfig> CredentialConfigs { get; set; }
}
public class ApplicationConfig
{
public string Name { get; set; }
public string Site { get; set; }
}
public class PathConfig
{
public string SourcePath { get; set; }
public string TargetPath { get; set; }
}
public class CredentialConfig
{
public string Username { get; set; }
public string password { get; set; }
}
Now trying to load JSON and getting below error,
using (var streamReader = new StreamReader(#"./Config.json"))
{
var X = JsonConvert.DeserializeObject<Configurations>(streamReader.ReadToEnd());
}
$exception {"Cannot deserialize the current JSON array (e.g. [1,2,3])
into type 'ConsoleApp8.Configurations' because the type requires a
JSON object (e.g. {\"name\":\"value\"}) to deserialize
correctly.\r\nTo fix this error either change the JSON to a JSON
object (e.g. {\"name\":\"value\"}) or change the deserialized type to
an array or a type that implements a collection interface (e.g.
ICollection, IList) like List that can be deserialized from a JSON
array. JsonArrayAttribute can also be added to the type to force it to
deserialize from a JSON array.\r\nPath '', line 1, position
1."} Newtonsoft.Json.JsonSerializationException
What else I need to serialize?
Your JSON represents an array - although the closing [ should be a ]. But you're trying to serialize it into a single Configurations object. Additionally, you seem to be expecting separate arrays for the application configs, path configs and credential configs - whereas your JSON shows an array of objects, each of which has all three.
I suspect you want:
public class Configuration
{
[JsonProperty("applicationConfig")]
ApplicationConfig ApplicationConfig { get; set; }
[JsonProperty("pathConfig")]
PathConfig PathConfig { get; set; }
[JsonProperty("credentialConfig")]
CredentialConfig CredentialConfig { get; set; }
}
// Other classes as before, although preferably with the password property more conventionally named
Then use:
List<Configuration> configurations =
JsonConvert.DeserializeObject<List<Configuration>>(streamReader.ReadToEnd());
You'll then have a list of configuration objects, each of which will have the three "subconfiguration" parts.
Your JSON class definition is close but not quite. Moroever the last [ must be ]
JSON class definition is created wtih QuickType
public partial class Configuration
{
[JsonProperty("applicationConfig")]
public ApplicationConfig ApplicationConfig { get; set; }
[JsonProperty("pathConfig")]
public PathConfig PathConfig { get; set; }
[JsonProperty("credentialConfig")]
public CredentialConfig CredentialConfig { get; set; }
}
public partial class ApplicationConfig
{
[JsonProperty("Name")]
public string Name { get; set; }
[JsonProperty("Site")]
public string Site { get; set; }
}
public partial class CredentialConfig
{
[JsonProperty("Username")]
public string Username { get; set; }
[JsonProperty("password")]
public string Password { get; set; }
}
public partial class PathConfig
{
[JsonProperty("SourcePath")]
public string SourcePath { get; set; }
[JsonProperty("TargetPath")]
public string TargetPath { get; set; }
}
Finally you need to serialize with
var config_list = JsonConvert.DeserializeObject<List<Configuration>>(streamReader.ReadToEnd());
I think it is a typo, you are opening the square bracket instead of closing it in the JSON file.
[ {
"applicationConfig": {
"Name": "Name1",
"Site": "Site1"
},
"pathConfig": {
"SourcePath": "C:\Temp\Outgoing1",
"TargetPath": "C:\Files"
},
"credentialConfig": {
"Username": "test1",
"password": "super1"
} }, {
"applicationConfig": {
"Name": "Name2",
"Site": "Site2"
},
"pathConfig": {
"SourcePath": "C:\Temp\Outgoing2",
"TargetPath": "C:\Files"
},
"credentialConfig": {
"Username": "test2",
"password": "super2"
} } [ <-HERE

How Can I deserialize a json that is an object with an array? using Newtonsoft xamarin

I am using Xamarin forms and Newtonsoft to deserialize
It doesn't work:
var itens = JsonConvert.DeserializeObject<List<Model.Loja>>(json);
Here is my JSON:
{
"one": {
"two": [
{
"cod": 142,
"nome": "name",
"phone": "23423",
"endereco": "address",
"cidade": "city"
},
{
"cod": 142,
"nome": "name",
"phone": "23423",
"endereco": "address",
"cidade": "city"
}
]
}
}
Your model needs to match your JSON structure. Try using these classes:
public class RootObject
{
public One one { get; set; }
}
public class One
{
public List<Loja> two { get; set; }
}
public class Loja
{
public int cod { get; set; }
public string nome { get; set; }
public string phone { get; set; }
public string endereco { get; set; }
public string cidade { get; set; }
}
Then deserialize like this:
List<Loja> items = JsonConvert.DeserializeObject<RootObject>(json).one.two;
You can make a specific model class for that json, try to use http://json2csharp.com/,
and then you can parse it using newtonsoft.
If you are using json2chsarp then your specific class will called RootObject, but you can rename it to match your model.
var obj = JsonConvert.DeserializeObject<YourSpecificClass>(json);
The problem was the "[ ]".
I used
response = json.Substring(json.IndexOf('['));
response = json.Substring(0, json.LastIndexOf(']') + 1);
And solved it.

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);
}
}

Categories