I've tried to get the values from the JSON object that I made a request from Google APIs. My goal is to get the data from transcript.
This is the JSON file.
{
"results": [
{
"alternatives": [
{
"transcript": "how old are you",
"confidence": 0.66882694
}
]
}
]
}
And I've tried to get the output by using this. But it doesn't work.
var result = ["result"][0]["alternative"][0]["transcript"].ToString()
When I query the data, It doesn't show anything, just empty string.
Convert your JSON to a class
Json2CSharp and you get:
public class Alternative
{
public string transcript { get; set; }
public double confidence { get; set; }
}
public class Result
{
public List<Alternative> alternatives { get; set; }
}
public class RootObject
{
public List<Result> results { get; set; }
}
Store it somewhere in your code.
Use Newtonsoft.Json package
Install Newtonsoft.Json NUGet Package in your solution and import it in your code:
using Newtonsoft.Json;
Now you can deserialize your json as you prefer as long as you have it in a string variable.
var yourObject = JsonConvert.DeserializeObject<RootObject>(jsonString);
You may access your transcript value using:
var transcript = yourObject.results[0].alternatives[0].transcript;
SOLUTION (without using external library like NewtonSoft.Json):
Add reference System.Web.Extensions.
use an assembly System.Web.Script.Serialization;
CODE:
var jsonString = "{\"results\": [ {\"alternatives\": [ {\"transcript\": \"how old are you\", \"confidence\": 0.66882694 } ] } ]}";
var jsonDeserialized = serializer.Deserialize<dynamic> (jsonString);
Console.WriteLine (jsonDeserialized["results"][0]["alternatives"][0]["transcript"]); // Prints "how old are you"
Your strings are JSON formatted, so you will need to parse it into a object. For that you can use JSON.NET.
Here is an example on how to parse a JSON string into a dynamic object:
string source = "{\r\n \"id\": \"100000280905615\", \r\n \"name\": \"Jerard Jones\", \r\n \"first_name\": \"Jerard\", \r\n \"last_name\": \"Jones\", \r\n \"link\": \"https://www.facebook.com/Jerard.Jones\", \r\n \"username\": \"Jerard.Jones\", \r\n \"gender\": \"female\", \r\n \"locale\": \"en_US\"\r\n}";
dynamic data = JObject.Parse(source);
Console.WriteLine(data.id);
.
Console which data you want show
Usually if I knew what the structure of the JSON looks like I would use class to parse it.
But you could always parse the string to JSON object anytime.
using Newtonsoft.Json.Linq;
var json=JObject.Parse(YOUR_JSON_STRING)
var result = json["results"][0]["alternative"][0]["transcript"].ToString()
https://dotnetfiddle.net/KSDcIP
Also your keys that you are requesting doesn't match the keys in the JSON
Related
C#
Let's say that I want to make a winform page that receives a certain amount of random features read from the contents of a json file. (while using the 'Newtonsoft.Json' library)
Code that Deserializes the json file
Root myDeserializedClass = JsonConvert.DeserializeObject<Root>(File.ReadAllText(#"..\..\Json\features.json"));
These classes are set to represent the contents and structure of the json file within the same c# file, but outside of the main class of course.
class Root
{
public List<Category> category { get; set; }
}
class Category
{
public string name { get; set; }
public List<Feature> feature { get; set; }
}
class Feature
{
public string name { get; set; }
public string frequency { get; set; }
}
I have followed the practices to make this happen here:
https://www.newtonsoft.com/json/help/html/DeserializeWithJsonSerializerFromFile.htm
Can not deserialize JSON with array in array
https://json2csharp.com/
It works, however there are two main problems I can see with this:
It can end up visually cluttering the .cs file with lots of classes that you'll never need to look or edit, especially when it is interpreting multiple json files
It isn't dynamic, and it will only work for one json file that you have to make compatible by creating these classes for every subclass that exists within the json file.
My question: Is there a way to deserialize the json file without having to resort to creating multiple classes for every sub-category of data in the json string?
I believe you don't need the classes, because you don't need the whole JSON string, is that correct?
If so, instead of deserializing the whole json file, you could partially deserialize only the parts which you are interested in.
Have a look at this example from the Newtonsoft.Json documentation, where we have a long json string representing a response from a Google search, but are only interested in the responseData/results part of it, and only in some fields of that result object:
Object to partially desierialize:
public class SearchResult
{
public string Title { get; set; }
public string Content { get; set; }
public string Url { get; set; }
}
Deserializing Partial JSON Fragment Example:
string googleSearchText = #"{
'responseData': {
'results': [
{
'GsearchResultClass': 'GwebSearch',
'unescapedUrl': 'http://en.wikipedia.org/wiki/Paris_Hilton',
'url': 'http://en.wikipedia.org/wiki/Paris_Hilton',
'visibleUrl': 'en.wikipedia.org',
'cacheUrl': 'http://www.google.com/search?q=cache:TwrPfhd22hYJ:en.wikipedia.org',
'title': '<b>Paris Hilton</b> - Wikipedia, the free encyclopedia',
'titleNoFormatting': 'Paris Hilton - Wikipedia, the free encyclopedia',
'content': '[1] In 2006, she released her debut album...'
},
{
'GsearchResultClass': 'GwebSearch',
'unescapedUrl': 'http://www.imdb.com/name/nm0385296/',
'url': 'http://www.imdb.com/name/nm0385296/',
'visibleUrl': 'www.imdb.com',
'cacheUrl': 'http://www.google.com/search?q=cache:1i34KkqnsooJ:www.imdb.com',
'title': '<b>Paris Hilton</b>',
'titleNoFormatting': 'Paris Hilton',
'content': 'Self: Zoolander. Socialite <b>Paris Hilton</b>...'
}
],
'cursor': {
'pages': [
{
'start': '0',
'label': 1
},
{
'start': '4',
'label': 2
},
{
'start': '8',
'label': 3
},
{
'start': '12',
'label': 4
}
],
'estimatedResultCount': '59600000',
'currentPageIndex': 0,
'moreResultsUrl': 'http://www.google.com/search?oe=utf8&ie=utf8...'
}
},
'responseDetails': null,
'responseStatus': 200
}";
// Parse JSON into a JObject, which we can easily traverse
JObject googleSearch = JObject.Parse(googleSearchText);
// get JSON result objects into a list
IList<JToken> results = googleSearch["responseData"]["results"].Children().ToList();
// serialize JSON results into .NET objects
IList<SearchResult> searchResults = new List<SearchResult>();
foreach (JToken result in results)
{
// JToken.ToObject is a helper method that uses JsonSerializer internally
SearchResult searchResult = result.ToObject<SearchResult>();
searchResults.Add(searchResult);
}
// Title = <b>Paris Hilton</b> - Wikipedia, the free encyclopedia
// Content = [1] In 2006, she released her debut album...
// Url = http://en.wikipedia.org/wiki/Paris_Hilton
// Title = <b>Paris Hilton</b>
// Content = Self: Zoolander. Socialite <b>Paris Hilton</b>...
// Url = http://www.imdb.com/name/nm0385296/
This way, we only need to create a class for SearchResult and for nothing else, which sounds like what you want to have. While traversing the JSON object with code like googleSearch["responseData"]["results"] you can check whether the result is null and act accordingly, which means you can have optional fields in your JSON file, which are not present in other files, without your code breaking.
Does this help you solve your issues?
I believe that best practice is using classes.
Here are my arguments for using classes in your case:
You can read json bit by bit, use JObject.Parse or even dynamic (ugh) but it think your code should depend on a class (a dto) not on a json string. This input structure happens to be stored in json, but may not be. Most of your unit tests should take in an object, not a string.
I find the argument of deserialising to classes not being dynamic weak because you need to write the code that will handle the added elements. In other words if you add a new feature to json it won't just work, you need to write the code to support it and each time you change the json structure you need to update your code anyway.
I have been trying to convert Json response to C# Array and the thing is Json goes up from my head I dont understand its structure as its a mess for me.
here is the example response I have as Json
{
"status":"ok",
"urls":{
"phone":[
{
"url":"tel:+9230154XXXXX",
"uri":"+9230154XXXXX"
}
],
"sms":{
"url":"sms:+9230154XXXXX",
"uri":"+9230154XXXXX"
},
"vcf":"https:\/\/www.eac.com\/i2\/ajax\/item\/vcf\/"
},
"limitExceeded":false
}
Now all i want from this Json sms:+9230154XXXXX this value.
I am using Newtonsoft.Json in this example.
Bellow is what I have tried so far
JObject jObject = JObject.Parse(json);
JToken jphone = jObject["urls"];
number = (string)jphone["phone"]["sms"];
Usage:
jObject["urls"]["phone"].ToObject<PhoneEntry[]>()
Class:
public class PhoneEntry {
[JsonProperty("url")]
public string Url { get; set; }
[JsonProperty("uri")]
public string Uri { get; set; }
}
I never really worked with Newtonsoft.Json but the following should work for you:
JToken token = JToken.Parse(json);
string number = (string)token.SelectToken("urls.sms.url")
I am faced with a problem.
I want to deserialize a complex JSON response from a server, but I only need one part of it.
Here is an example:
{
"menu": {
"id": "file",
"value": "File",
"popup": {
"menuitem": [
{"value": "New", "onclick": "CreateNewDoc()"},
{"value": "Open", "onclick": "OpenDoc()"},
{"value": "Close", "onclick": "CloseDoc()"}
]
}
}
}
I also used Csharp2json to get the class objects that I need, I just modified the menu class according to my needs :
public class Menuitem
{
public string value { get; set; }
public string onclick { get; set; }
}
public class Popup
{
public IList<Menuitem> menuitem { get; set; }
}
public class Menu
{
public Popup popup { get; set; }
}
public class RootObjectJourney
{
public Menu menu { get; set; }
}
Now, how do I deserialize if I only need the popup value and his children?
You can actually utilize the Linq namespace of the NewtonSoft.Json and modify your code little bit to get only the "popup" elements from the JSON.
your class structure remains the same. Make sure you use the namespace(s)
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
then in your code once you have the JSON string with you, you can use the "JObject" static method "Parse" to parse the JSON, like
var parsedObject = JObject.Parse(jsonString);
This will give you the JObject with which you can access all your JSON Keys just like a Dictionary.
var popupJson = parsedObject["menu"]["popup"].ToString();
This popupJson now has the JSON only for the popup key.
with this you can use the JsonConvert to de- serialize the JSON.
var popupObj = JsonConvert.DeserializeObject<Popup>(popupJson);
this popupObj has only list of menuitems.
If you do not use Newtonsoft and are using System.Text.Json in .NET Core, you can use this:
var post = JsonDocument.Parse(stringifiedJson);
var cat = post.RootElement.GetProperty("category").GetString();
You see GetString here to cast the value to string, there are other overloads available to cast the json value to Int32 etc.
If the intend is to deserialize only one property, I generally perefer to use JsonPath due to its flexibility. Please check the code below
var jsonQueryString = "{ 'firstName': 'John',
'lastName' : 'doe',
'age' : 26,}";
JObject o = JObject.Parse(jsonQueryString);
JToken token= o.SelectToken("$.age");
Console.WriteLine(token);
If your Json is complex, you can use power of JsonPath.
you can check https://support.smartbear.com/readyapi/docs/testing/jsonpath-reference.html#examples for JsonPath detailed documentation and examples.
I also included example below for further usage information:
JObject o = JObject.Parse(#"{
'store': {
'book': [
{
'category': 'history',
'author': 'Arnold Joseph Toynbee',
'title': 'A Study of History',
'price': 5.50
},
...
]
},
'expensive': 10
}");
//gets first book object
Console.WriteLine(o.SelectToken("$..book[0]"));
//get first book's title
Console.WriteLine(o.SelectToken("$..book[0].title"));
// get authors of the books where the books are cheaper then 10 $
foreach (var token in o.SelectTokens("$..[?(#.price < 10)].author"))
Console.WriteLine(token);
.NET 5+
The solution is very simple:
using System.Text.Json;
var doc = JsonDocument.Parse(response.Content);
var popupJson= doc.RootElement.GetProperty("menu").GetProperty("popup");
I have this structure:
{
"longUrl" :"http://www.sample.com",
"bok" :1,
"url" :"http://pleasegetme.com ",
"title" :""
}
//equivalent
"{
\n \"longUrl\" :\"http://www.sample.com/\",
\n \"bok\" :1,
\n \"url\" :\"http://pleasegetme.com \",
\n \"title\" :\"\"\n
}"
I have this function
public string Domain1Helper(string longText)
{
Regex rgxUrl = new Regex("\"url\":\"(.*?)\"");
Match mUrl = rgxUrl.Match(longText);
string url = Regex.Replace(mUrl.Groups[1].Value, #"\\", "");
return url;
}
What I want to get is http://pleasegetme.com.
What is the wrong in my Domain1Helper method?
What you have there is a JSON string. You can parse this using a library called Json.Net. You can find this as a nuget package. You can then use the following code to pick out the strings you want.
JObject jo = JObject.Parse(longtext);
Console.WriteLine(jo["longUrl"].Value.ToString()); // Outputs 'http://www.sample.com'
AJB, You have an error in your RegEx.
That being said you should use a JSON deserializer, like JSON.NET.
In the function Domain1Helper it should be:
Regex rgxUrl = new Regex("\"url\"\\s+:\"(.*?)\"");
Notice the \s+ ?
You have included the escape strings \. If you remove those, it should parse just fine, as in here:
https://regex101.com/r/hK7xR7/1
Note, that you method should look like this:
public string Domain1Helper(string longText)
{
Regex rgxUrl = new Regex(#"\"url\" :\"(.*?)\"");
Match mUrl = rgxUrl.Match(longText);
string url = Regex.Replace(mUrl.Groups[1].Value, #"\\", "");
return url;
}
And alternative solution would be using one json library, which is outlined here: https://msdn.microsoft.com/en-us/library/cc197957(v=vs.95).aspx
It is a freaking JSON formatted string. Use a JSON deserializer such as JSON.NET. I'll leave it to you on which one you'd want to use.
Here is the root object generated using json2csharp.com
public class RootObject
{
public string longUrl { get; set; }
public int bok { get; set; }
public string url { get; set; }
public string title { get; set; }
}
Example using JSON.NET:
using Newtonsoft.Json; // Namespace is something like this
string json = "{
\n \"longUrl\" :\"http://www.sample.com/\",
\n \"bok\" :1,
\n \"url\" :\"http://pleasegetme.com \",
\n \"title\" :\"\"\n
}";
RootObject rootObject = JsonConvert.DeserializeObject<RootObject>(json);
string url = rootObject.url;
// Do something with the url
Does anyone know how to convert a string which contains json into a C# array. I have this which reads the text/json from a webBrowser and stores it into a string.
string docText = webBrowser1.Document.Body.InnerText;
Just need to somehow change that json string into an array. Been looking at Json.NET but I'm not sure if that's what I need, as I don't want to change an array into json; but the other way around. Thanks for the help!
just take the string and use the JavaScriptSerializer to deserialize it into a native object. For example, having this json:
string json = "[{Name:'John Simith',Age:35},{Name:'Pablo Perez',Age:34}]";
You'd need to create a C# class called, for example, Person defined as so:
public class Person
{
public int Age {get;set;}
public string Name {get;set;}
}
You can now deserialize the JSON string into an array of Person by doing:
JavaScriptSerializer js = new JavaScriptSerializer();
Person [] persons = js.Deserialize<Person[]>(json);
Here's a link to JavaScriptSerializer documentation.
Note: my code above was not tested but that's the idea Tested it. Unless you are doing something "exotic", you should be fine using the JavascriptSerializer.
using Newtonsoft.Json;
Install this class in package console
This class works fine in all .NET Versions, for example in my project: I have DNX 4.5.1 and DNX CORE 5.0 and everything works.
Firstly before JSON deserialization, you need to declare a class to read normally and store some data somewhere
This is my class:
public class ToDoItem
{
public string text { get; set; }
public string complete { get; set; }
public string delete { get; set; }
public string username { get; set; }
public string user_password { get; set; }
public string eventID { get; set; }
}
In HttpContent section where you requesting data by GET request
for example:
HttpContent content = response.Content;
string mycontent = await content.ReadAsStringAsync();
//deserialization in items
ToDoItem[] items = JsonConvert.DeserializeObject<ToDoItem[]>(mycontent);
Yes, Json.Net is what you need. You basically want to deserialize a Json string into an array of objects.
See their examples:
string myJsonString = #"{
"Name": "Apple",
"Expiry": "\/Date(1230375600000+1300)\/",
"Price": 3.99,
"Sizes": [
"Small",
"Medium",
"Large"
]
}";
// Deserializes the string into a Product object
Product myProduct = JsonConvert.DeserializeObject<Product>(myJsonString);
Old question but worth adding an answer if using .NET Core 3.0 or later. JSON serialization/deserialization is built into the framework (System.Text.Json), so you don't have to use third party libraries any more. Here's an example based off the top answer given by #Icarus
using System;
using System.Collections.Generic;
namespace ConsoleApp
{
class Program
{
static void Main(string[] args)
{
var json = "[{\"Name\":\"John Smith\", \"Age\":35}, {\"Name\":\"Pablo Perez\", \"Age\":34}]";
// use the built in Json deserializer to convert the string to a list of Person objects
var people = System.Text.Json.JsonSerializer.Deserialize<List<Person>>(json);
foreach (var person in people)
{
Console.WriteLine(person.Name + " is " + person.Age + " years old.");
}
}
public class Person
{
public int Age { get; set; }
public string Name { get; set; }
}
}
}
One Situation that wasn't covered in the other responses is when you don't know the type of what the JSON object contains. That was my case as I needed to be able to NOT type it and leave it dynamic.
var objectWithFields = js.Deserialize<dynamic[]>(json);
Note: it is definitely preferred to have a type, in some cases, it is not possible, that's why I added this answer.