I'm using the last GraphQL client NuGet package (3.2.1) on .NET Core 3.1 project and calling a GraphQL API.
When I do the "SendQueryAsync()" or "SendMutationAsync()" the response status code is OK but the Data property is always Null.
I think it's related to the serialization but idk where is the problem.
How I use it
var graphQLClient = new GraphQLHttpClient(new GraphQLHttpClientOptions { EndPoint = new Uri(_graphQLEndPoint) }, new NewtonsoftJsonSerializer(), httpclient);
var request = new GraphQLRequest
{
Query = #"query CurrentUserCards {
currentUser {
cardsCount
cards {
name
pictureUrl
position
player {
displayName
}
}
}
}"
};
var data = await graphQLClient.SendQueryAsync<Data>(request);
Even if I put "Rootobject" class it's null.
My model
I generated my model with "Paste JSON as classes" feature on Visual studio, from the JSON result.
public class Rootobject
{
public Data data { get; set; }
}
public class Data
{
public Currentuser currentUser { get; set; }
}
public class Currentuser
{
public int cardsCount { get; set; }
public Card[] cards { get; set; }
}
public class Card
{
public string name { get; set; }
public string pictureUrl { get; set; }
public string position { get; set; }
public Player player { get; set; }
}
public class Player
{
public string displayName { get; set; }
}
Response from Postman
{
"data": {
"currentUser": {
"cardsCount": 12,
"cards": [
{
"name": "Henry",
"pictureUrl": "",
"position": "Coach",
"player": {
"displayName": "Thierry Henry",
}
},
{
"name": "Zidane",
"pictureUrl": "",
"position": "Coach",
"player": {
"displayName": "Zinedine Zidane",
}
}
...
]
}
}
}
I have solved this by removing the Rootobject class and use the Data class as root. I think that the response always has a data property so it skips that in the deserialization.
Related
I created a class for a json object (not automatically).
However, I don't quite understand how to make the button object contain nameless arrays as in the example?
Example JSON (what the server expects to receive):
{
"one_time":false,
"buttons":[
[
{
"action":{
"type":"location",
"payload":"{\"button\": \"1\"}"
}
}
],
[
{
"action":{
"type":"open_app",
"app_id":6232540,
"owner_id":-157525928,
"hash":"123",
"label":"LiveWidget"
}
}
],
[
{
"action":{
"type":"vkpay",
"hash":"action=transfer-to-group&group_id=181108510&aid=10"
}
}
],
[
{
"action":{
"type":"text",
"payload":"{\"button\": \"1\"}",
"label":"Red"
},
"color":"negative"
},
{
"action":{
"type":"text",
"payload":"{\"button\": \"2\"}",
"label":"Green"
},
"color":"positive"
},
{
"action":{
"type":"text",
"payload":"{\"button\": \"2\"}",
"label":"Blue"
},
"color":"primary"
},
{
"action":{
"type":"text",
"payload":"{\"button\": \"2\"}",
"label":"White"
},
"color":"secondary"
}
]
]
}
Keyboard.cs (manually created class)
public class Keyboard
{
public bool one_time { get; set; }
public List<buttons> buttons { get; set; }
}
public class buttons
{
public action action { get; set; }
public string color { get; set; }
}
public class action
{
public string type { get; set; }
public string payload { get; set; }
public string label { get; set; }
}
I create an object like this:
var Keyboard_obj = new Keyboard()
{
one_time = false,
buttons = new List<buttons>()
{
new buttons()
{
action = new action()
{
type = "test1",
label = "class obj",
payload = "{\"button\": \"1\"}"
},
color = "negative"
},
new buttons()
{
action = new action()
{
type = "test2",
label = "class obj",
payload = "{\"button\": \"2\"}"
},
color = "positive"
}
}
};
How can I remake the class so that I get a JSON object like the example above?
You should use JsonSerializer
this code will give you a Json object like the example above:
var output = JsonConvert.SerializeObject(Keyboard_obj );
you can also create an object from Json:
Keyboard keyboard = JsonConvert.DeserializeObject<Keyboard>(output );
I can suggest you to try using dynamic objects
dynamic myObject = JsonConvert.DeserializeObject<dynamic>(input);
decimal Amount = Convert.ToDecimal(myObject.Amount);
string Message = myObject.Message;
If you take your JSON and use Visual studio (use paste as special option) or online tool to generate classes from the provided JSON then following classes will be generated.
Note - RootBoject.buttons Is an array or array instead of single collection.
public class Rootobject
{
public bool one_time { get; set; }
public Button[][] buttons { get; set; }
}
public class Button
{
public Action action { get; set; }
public string color { get; set; }
}
public class Action
{
public string type { get; set; }
public string payload { get; set; }
public int app_id { get; set; }
public int owner_id { get; set; }
public string hash { get; set; }
public string label { get; set; }
}
So with the provided class schema if you use JsonConvert to searialize the RootObject then you will get the required JSON.
I need to get GET response from REST API. I use RestSharp. The problem is, that one name of the response attribute is "$". This is the response:
[
{
"CodeId": {
"$": "00000000"
},
"Entity": {
"LegalName": {
"#xml:lang": "cs",
"$": "xxxxx"
}
}
}
]
How should I use the RestSharp to get the value of Entity.LegalName.$ ?
I found the answer thanks by #fredrik.
var client = new RestClient(url);
var request = new RestRequest(urlRequest, DataFormat.Json);
var response = client.Get(request);
Console.WriteLine(JsonSerializer.Deserialize<List<TestRestResponseTemplate>>(response.Content)[0].Entity.LegalName.Value);
TestRestResponseTemplate:
public class TestRestResponseTemplate
{
public Entity Entity { get; set; }
}
public class LegalName
{
[JsonPropertyName("#xml:lang")]
public string Language { get; set; }
[JsonPropertyName("$")]
public string Value { get; set; }
}
public class Entity
{
public LegalName LegalName { get; set; }
}
I am trying to get a field from the response from the rest services in the Web API we are building. The JSON looks like this:
{
"d": {
"results": [{
"__metadata": {
"id": "Web/Lists(guid'4ddc-41e2-bb44-0f92ad2c0b07')/Items(164)",
"uri": "https://teams.ax.org/sites/js/project/_api/Web/Lists(guid'4ddc-41e2-bb44-0f92ad2c0b07')/Items(164)",
"etag": "\"6\"",
"type": "SP.Data.St_x0020_CdsListItem"
},
"Folder": {
"__deferred": {
"uri": "https://teams.ax.org/sites/js/project/_api/Web/Lists(guid'4ddc-41e2-bb44-0f92ad2c0b07')/Items(164)/Folder"
}
},
"ParentList": {
"__deferred": {
"uri": "https://teams.ax.org/sites/js/project/_api/Web/Lists(guid'4ddc-41e2-bb44-0f92ad2c0b07')/Items(164)/ParentList"
}
},
"PM_x0020_NameId": 220,
"St_x0020_Name": "<div class=\"ExternalClassA14DB0FF86994403B827D91158CF34B0\">KO</div>",
}]
}}
I created these model classes:
public class SharepointDTO
{
public class Metadata
{
[JsonProperty("id")]
public string id { get; set; }
[JsonProperty("uri")]
public string uri { get; set; }
[JsonProperty("etag")]
public string etag { get; set; }
[JsonProperty("type")]
public string type { get; set; }
}
public class Deferred
{
[JsonProperty("uri")]
public string uri { get; set; }
}
public class Folder
{
[JsonProperty("__deferred")]
public Deferred __deferred { get; set; }
}
public class ParentList
{
[JsonProperty("__deferred")]
public Deferred __deferred { get; set; }
}
public class Result
{
[JsonProperty("__metadata")]
public Metadata __metadata { get; set; }
[JsonProperty("Folder")]
public Folder Folder { get; set; }
[JsonProperty("ParentList")]
public ParentList ParentList { get; set; }
[JsonProperty("PM_x0020_NameId")]
public int PM_x0020_NameId { get; set; }
[JsonProperty("St_x0020_Name")]
public string St_x0020_Name { get; set; }
}
public class D
{
[JsonProperty("results")]
public IList<Result> results { get; set; }
}
public class RootObject
{
[JsonProperty("d")]
public D d { get; set; }
}
}
No trying to call the rest service from the Web API and need to get the St_x0020_Name from response and store in a string.
SharepointDTO.RootObject retSharepointobj = await GetfromSharepoint(StNumber);
string StName = retSharepointobj.d.results.St_x0020_Name.ToString();
I am deserializing the JSON in the GetfromSharepoint method like
using (var client_sharePoint = new HttpClient(handler))
{
var response = client_sharePoint.GetAsync(SP_URL).Result;
var responsedata = await response.Content.ReadAsStringAsync();
var returnObj = JsonConvert.DeserializeObject<SharepointDTO.RootObject>(responsedata);
return returnObj;
}
But it throws an error:
'System.Collections.Generic.IList' does not contain a definition for 'St_x0020_Name' and no extension method 'St_x0020_Name' accepting a first argument of type 'System.Collections.Generic.IList' could be found (are you missing a using directive or an assembly reference?)
results is an array, so you have either loop thru like
foreach(var item in retSharepointobj.d.results){
string StName = item.St_x0020_Name.ToString();
}
or get a specific element, for example a first element like:
SharepointDTO.RootObject retSharepointobj = await GetfromSharepoint(StNumber);
string StName = retSharepointobj.d.results[0].St_x0020_Name.ToString();
or you can add an extra check like that
SharepointDTO.RootObject retSharepointobj = await GetfromSharepoint(StNumber);
if(retSharepointobj.d.results.length > 0){
string StName = retSharepointobj.d.results[0].St_x0020_Name.ToString();
}
Shouldn't this line:
string StName = retSharepointobj.d.results.St_x0020_Name.ToString();
Be like this?
string StName = retSharepointobj.d.results.First().St_x0020_Name.ToString();
Here is my json data
{
"found": 501,
"posts": [
{
"ID": 2500,
"site_ID": 1,
"date": "2014-09-26T15:58:23-10:00",
"modified": "2014-09-26T15:58:23-10:00",
"title": "DOD HQ Visitors Parking",
"metadata": [
{
"id": "15064",
"key": "city",
"value": "Honolulu County"
},
{
"id": "15067",
"key": "country",
"value": "US"
},
{
"id": "15062",
"key": "floor_level",
"value": "Ground Floor"
}
]
}
],
"_headers": {
"Date": "Fri, 13 Feb 2015 09:21:55 GMT",
"Content-Type": "application/json"
}
}
I used model class generated from http://json2csharp.com/
public class Metadata
{
public string id { get; set; }
public string key { get; set; }
public string value { get; set; }
}
public class Post
{
public int ID { get; set; }
public int site_ID { get; set; }
public string date { get; set; }
public string modified { get; set; }
public string title { get; set; }
public List<Metadata> metadata { get; set; }
}
public class Headers
{
public string Date { get; set; }
public string __invalid_name__Content-Type { get; set; }
}
public class RootObject
{
public int found { get; set; }
public List<Post> posts { get; set; }
public Headers _headers { get; set; }
}
I don't know if this is the correct way of Parsing JSON array, I want to put the data collected into a ObservableCollection to be used in binding my Listview in XAML Page.
public class SpacesViewModel
{
public ObservableCollection<Space> Spaces { get; set; }
public SpacesViewModel()
{
Spaces = new ObservableCollection<Space>();
this.LoadSpaces();
}
async private void LoadSpaces()
{
var client = new HttpClient();
string json = await client.GetStringAsync("http://localhost/allspaces.json");
var resultObjects = AllChildren(JObject.Parse(json))
.First(c => c.Type == JTokenType.Array && c.Path.Contains("posts"))
.Children<JObject>();
foreach (JObject post in resultObjects)
{
Debug.WriteLine(post["title"]);
foreach (var metadata in post["metadata"])
{
var key = metadata["key"].ToString();
if (key == "city")
Debug.WriteLine(metadata["value"].ToString());
if (key == "street_address")
Debug.WriteLine(metadata["value"].ToString());
}
}
}
private static IEnumerable<JToken> AllChildren(JToken json)
{
foreach (var c in json.Children())
{
yield return c;
foreach (var cc in AllChildren(c))
{
yield return cc;
}
}
}
}
A possible approach is to use the Newtonsofts Json.NET libary. You can easily get it as nuget. After adding the nuget you can simply parse a collection (nested collections are working as well) with:
using Newtonsoft.Json;
...
string json = await client.GetStringAsync("http://localhost/allspaces.json");
List<Post> parsedPosts = JsonConvert.DeserializeObject<List<Post>>(json);
After getting the posts as List, you can add them to your ObservableCollection.
How can I query (to see if a property exists) and enumerate (the array property) found within a complex JSON object using using JSON.NET in C# ?
I am receiving a complex JSON object from an API with a variable number/type of properties.
I keep reading the JSON.Net Documentation, reviewing samples, etc. but not gotten far and am lost in JObject, JArray, JToken, using dynamic, etc...
I want to find the pageResponses.scriptOutput property, verify it contains and .items[] array and then enumerate/iterate the array.
Edit
I made progress and found typo in JSON data example.
But how can I query/enumerate the child objects using key names, e.g.(item.location, item.timestamp) ?
string json = File.ReadAllText(#"Output.json");
JObject jObj = JObject.Parse(json);
IList<JToken> items = jObj["pageResponses"][0]["scriptOutput"]["items"].ToList();
foreach (JToken item in items){
Console.WriteLine(item["location"]);
}
/*** Console Output ***/
// Austin, TX
// Anaheim, CA
// Adams, MN
// Barstow, CA
var varItems = from o in jObj["pageResponses"][0]["scriptOutput"]["items"].ToList() select o;
foreach (var item in varItems){
Console.WriteLine(item["timestamp"]);
}
/*** Console Output ***/
// 2016 - 05 - 03 19:53
// 2016 - 05 - 04 04:10
// 2016 - 05 - 04 08:18
// 2016 - 05 - 01 12:26
(JSON sample below trimmed down for brevity)
{
"meta": {
"outputAsJson": true,
"backend": {
"os": "linux",
"id": "10.240.0.3_2",
"requestsProcessed": 8
}
},
"pageResponses": [
{
"pageRequest": {
"renderType": "script",
"outputAsJson": true
},
"frameData": {
"name": "",
"childCount": 1
},
"events": [
{
"key": "navigationRequested",
"time": "2016-05-06T13:43:30.344Z"
},
{
"key": "navigationRequested",
"time": "2016-05-06T13:43:31.131Z"
}
],
"scriptOutput": {
"items": [
{
"location": "Austin, TX",
"timestamp": "2016-05-03 19:53",
"title": "User Login"
},
{
"location": "Anaheim, CA",
"timestamp": "2016-05-04 04:10",
"title": "User Logout"
},
{
"location": "Adams, MN",
"timestamp": "2016-05-04 08:18",
"title": "User Login"
},
{
"location": "Barstow, CA",
"timestamp": "2016-05-01 12:26",
"title": "User Logout"
}
]
},
"statusCode": 200
}
],
"statusCode": 200,
"content": {
"name": "content.json",
"encoding": "utf8"
},
"originalRequest": {
"pages": [
{
"renderType": "script",
"outputAsJson": true
}
]
}
}
I suggest creating a proxy class (I used json2csharp):
public class Backend
{
public string os { get; set; }
public string id { get; set; }
public int requestsProcessed { get; set; }
}
public class Meta
{
public bool outputAsJson { get; set; }
public Backend backend { get; set; }
}
public class PageRequest
{
public string renderType { get; set; }
public bool outputAsJson { get; set; }
}
public class FrameData
{
public string name { get; set; }
public int childCount { get; set; }
}
public class Event
{
public string key { get; set; }
public string time { get; set; }
}
public class ScriptOutput
{
public List<object> items { get; set; }
}
public class PageRespons
{
public PageRequest pageRequest { get; set; }
public FrameData frameData { get; set; }
public List<Event> events { get; set; }
public ScriptOutput scriptOutput { get; set; }
public int statusCode { get; set; }
}
public class Content
{
public string name { get; set; }
public string encoding { get; set; }
}
public class Page
{
public string renderType { get; set; }
public bool outputAsJson { get; set; }
}
public class OriginalRequest
{
public List<Page> pages { get; set; }
}
public class RootObject
{
public Meta meta { get; set; }
public List<PageRespons> pageResponses { get; set; }
public int statusCode { get; set; }
public Content content { get; set; }
public OriginalRequest originalRequest { get; set; }
}
Then deserialize it:
var obj = JsonConvert.DeserializeObject<RootObject>(json);
if (obj != null && obj.pageResponses != null)
{
foreach (var pageResponse in obj.pageResponses)
{
if (pageResponse.scriptOutput == null)
continue;
foreach (var item in pageResponse.scriptOutput.items)
{
Console.WriteLine(item);
}
}
}
I do this with a couple of Extension Methods and I use JsonConvert.DeserializeObject.
Code snippets below.
Usage
ExpandoObject data = JsonConvert.DeserializeObject<ExpandoObject>(jsonString);
if(data.HasProperty("propertyToCheck"))
{
object[] objects = data.Get<object[]>("propertyToCheck");
}
In the snippet above I check a property exists, then I assign it to a .Net type, in this case an object array. Though it can be any type so long as it's sane.
Extension Methods
public static bool HasProperty(this ExpandoObject value, string property)
{
bool hasProp = false;
if (((IDictionary<String, object>)value).ContainsKey(property))
{
hasProp = true;
}
return hasProp;
}
public static T Get<T>(this ExpandoObject value, string property)
{
return (T)((IDictionary<String, dynamic>)value)[property];
}
Quick, easy and to the point!