Unable to deserialize the JSON Data - c#

I'm currently using an API to grab some player information, which looks like this in raw data form:
{
"response": {
"players": [
{
"steamid": "76561198166559342",
"communityvisibilitystate": 1,
"profilestate": 1,
"personaname": "Stack Overflow",
"commentpermission": 2,
"profileurl": "https://steamcommunity.com/id/stackoverflow/",
"avatar": "https://avatars.akamai.steamstatic.com/8a2e52a3eaefed0296459fa811aasdasd1ce29374.jpg",
"avatarmedium": "https://avatars.akamai.steamstatic.com/8a2e52a3eaefed0296459fa81asdas1ce29374_medium.jpg",
"avatarfull": "https://avatars.akamai.steamstatic.com/8a2e52a3eaefed0296459fa811a61212312e29374_full.jpg",
"avatarhash": "8a2e52a3eaefed02asdasd",
"personastate": 0
}
]
}
}
I am trying to just grab the "personaname" and "avatar" values from my data, which have been quite unsuccessful, so I've tried to objectify the JSON before getting it, which still isn't working:
Models.SteamUser persona;
String httpres;
using (var client = new HttpClient())
{
string steamurl = "MY HIDDEN URL HERE" + s64;
var steamapi = new Uri(steamurl);
var result = client.GetAsync(steamapi).Result.Content.ReadAsStringAsync().Result;
var json = result.ToString();
httpres = json;
var jUser = JObject.Parse(json);
var userData = JsonConvert.DeserializeObject<Models.SteamUser>(jUser["players"]).ToString(); ;
persona = userData;
}
Is there something I'm missing?

To get players from the JSON response, you need jObj["response"]["players"] instead of jObj["players"].
You have to deserialize as List<Models.SteamUser> but not Models.SteamUser as it is an array. Then with IEnumerable.FirstOrDefault() to get the first item of the array.
From the existing code, the userData is string type while persona is List<Models.SteamUser> type. You can't assign userData to persona.
Not suggested using Task.Result as it performs the operation synchronously and waits for the operation to be completed. Hence, it may lead to a deadlock. Instead, works with async/await. Source: What happens while waiting on a Task's Result?
Your code should be looked as below:
Models.SteamUser persona = null;
using (var client = new HttpClient())
{
string steamurl = "MY HIDDEN URL HERE" + s64;
var steamapi = new Uri(steamurl);
var response = await client.GetAsync(steamapi);
var jsonResult = await response.Content.ReadAsStringAsync();
var jObj = JObject.Parse(jsonResult);
var players = JsonConvert.DeserializeObject<List<Models.SteamUser>>(jObj["response"]["players"].ToString());
// Or
// var players = (jObj["response"]["players"] as JArray).ToObject<List<Models.SteamUser>>();
persona = players.FirstOrDefault();
}

Related

How to use an information sent on httpResponse?

I am learning about making requests to an api using my backend and when i make this i receive a response with some informations i want to use but i don't know how to use this.
Let me clarify this for you.
I HAVE THIS CODE TO MAKE THE REQUEST
try
{
//Set Basic Auth
var userPagarme = test_key;
var password = "";
var base64String = Convert.ToBase64String(Encoding.ASCII.GetBytes($"{userPagarme}:{password}"));
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", base64String);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var clienteToAdd = new PagarmeCliente()
{
Name = registerUser.Name,
Code = registerUser.Code,
Document = registerUser.Document,
Type = registerUser.Type,
Document_Type = registerUser.Document_Type,
Birthdate = registerUser.Birthdate,
Email = registerUser.Email,
Gender = registerUser.Gender,
Address = new PagarmeClienteEndereco()
{
city = registerUser.City,
country = registerUser.Country,
line_1 = registerUser.Line_1,
line_2 = registerUser.Line_2,
state = registerUser.State,
zip_code = registerUser.Zip_Code
},
Phones = new PagarmeClienteTelefone()
{
mobile_phone = new PagarmeClienteTelefoneMobile()
{
area_code = registerUser.Mobile_phone_area_code,
country_code = registerUser.Mobile_phone_country_code,
number = registerUser.Mobile_phone_number
},
}
};
var jsonString = JsonConvert.SerializeObject(clienteToAdd);
HttpResponseMessage response = await client.PostAsJsonAsync(urlPagarme + "customers", clienteToAdd);
response.EnsureSuccessStatusCode();
string responseBody = await response.Content.ReadAsStringAsync();
this.responseBodyJSON = JsonConvert.DeserializeObject(responseBody); // I have created this prop as an OBJ to receive the obj that was sent. I don't know if it is correct
}
catch (HttpRequestException e)
{
return BadRequest("\nException Caught - Message :{0} " + e.Message);
}
That is what i have in this responseBodyJSON and i want to use this property ID to insert on my database but if i make something like this below it doesn't work:
string idThatIWant = responseBodyJSON.id... or something like that.
var jsonString = JsonConvert.SerializeObject(clienteToAdd);
HttpResponseMessage response = await client.PostAsJsonAsync(urlPagarme + "customers", clienteToAdd);
You converted your model to JSON but you didn't use that jsonString. This could be the cause of the problem.
var respBody = JsonConvert.DeserializeObject<PagarmeCliente>(responseBody);
respBody.ID should be available if the class PagarmeCliente has the ID field you wanted populated.

How to create exact JSON format to POST method in c# code?

Web Service required this format:
{
"Data":"{\"Name\":\"HelloWorld\",\"BirthDate\":\"2020-03-03\",\"BirthPlace\":\"Nowhere\"}"
}
I required above format to post to web service but my code below doesn't fulfil the format. Please help. I've been using below code to post
var Data = JsonConvert.SerializeObject(new
{
Data = new
{
Name= "HelloWorld",
BirthDate = "2020-03-03",
BirthPlace= "Nowhere"
}
});
using (var client = new HttpClient())
{
HttpResponseMessage response = await client.PostAsJsonAsync(apiUrl, Data);
}
If data should contains a string serialization of the real object. You can simply serialize the inner object using the string result as value on your second serialization.
using Newtonsoft.Json;
public static string WrapAndSerialize(object value){
return JsonConvert.SerializeObject(new { Data = JsonConvert.SerializeObject(value) });
}
Using it like:
var myObject=
new
{
Name = "HelloWorld",
BirthDate = "2020-03-03",
BirthPlace = "Nowhere",
};
var Data= WrapAndSerialize(myObject);
using (var client = new HttpClient())
{
HttpResponseMessage response = await client.PostAsJsonAsync(apiUrl, Data);
}
LiveDemo
To get the required format do:
string name = "HelloWorld";
string birthdate = "2020-03-03";
string birthplace= "Nowhere";
var jsonData = JsonConvert.SerializeObject(new
{
Data = $"\"Name\"=\"{name}\",\"BirthDate\"=\"{birthdate}\",\"BirthPlace\"=\"{birthplace}\""
});
See it in action: https://dotnetfiddle.net/UBXDtd
The format states that Data shall contain a string. Your code serializes an object with properties, which results in:
{"Data":{"Name":"HelloWorld","BirthDate":"2020-03-03","BirthPlace":"Nowhere"}}
EDIT: While this works, I would recommend #xdtTransform's answer over this. Leaving this here, in case his solution is for some reason not applicable.

Consume and Configure Graphql request from .Net C# console application client

I'm trying to consume a Graphql Api from a C# client. For that I'm using the GraphQl.Net Nuget package. The problem is that, I have no idea how to set the Api Url as I don't have HttpRequest object and this results also with additional problems that I can't set the authentcation header and send the token with the request. My code looks like:
public void Post(TestGraphQl.GraphQLQuery query)
{
var inputs = query.Variables.ToInputs();
var queryToExecute = query.Query;
var result = _executer.ExecuteAsync(_ =>
{
_.Schema = _schema;
_.Query = queryToExecute;
_.OperationName = query.OperationName;
_.Inputs = inputs;
//_.ComplexityConfiguration = new ComplexityConfiguration { MaxDepth = 15 };
_.FieldMiddleware.Use<InstrumentFieldsMiddleware>();
}).Result;
var httpResult = result.Errors?.Count > 0
? HttpStatusCode.BadRequest
: HttpStatusCode.OK;
var json = _writer.Write(result);
}
And the caller looks like this:
var jObject = new Newtonsoft.Json.Linq.JObject();
jObject.Add("id", deviceId);
client.Post(new GraphQLQuery { Query = "query($id: String) { device (id: $id) { displayName, id } }", Variables = jObject });
I'm totally new to this topic and appreciate any help. Many thanks!!
This worked out for me. You will need the GraphQL.Client Package. My_class is the class for the deserialization.
var client = new GraphQLHttpClient(Api_Url, new NewtonsoftJsonSerializer());
var request = new GraphQLRequest
{
Query = {query}
};
var response = await client.SendQueryAsync<my_class>(request);
Not sure if you are still looking for it. One can always use GraphQl.Client nuget to achieve this. Sample code to consume is
var query = #"query($id: String) { device (id: $id) { displayName, id } }";
var request = new GraphQLRequest(){
Query = query,
Variables = new {id =123}
};
var graphQLClient = new GraphQLClient("http://localhost:8080/api/GraphQL");
graphQLClient.DefaultRequestHeaders.Add("Authorization", "yourtoken");
var graphQLResponse = await graphQLClient.PostAsync(request);
Console.WriteLine(graphQLResponse.Data);

How do I deserialize only a property value from a JSON string?

I'm experimenting with JWT auth in a Web API project, and this is the code that fetches the token:
public static async Task Main(string[] args)
{
var login = new {username = "mario", password = "secret"};
var content = new StringContent(JsonConvert.SerializeObject(login), Encoding.UTF8, "application/json");
var resp = await _client.PostAsync("api/Token", content);
var json = await resp.Content.ReadAsStringAsync();
}
Yet the end value of json looks something like:
{ "token":"eyJhbGciOiJIUz...AXRbztetz_WhI"}
I would like to do something like:
var token = JsonConvert.DeserializeObject<???>(json);
but when I use
JsonConvert.DeserializeObject<string>(json)
I get a JsonReaderException:
Unexpected character encountered while parsing value: {. Path '', line
1, position 1.
Now how do I deserialize that json to get the string value of the token property?
You can do something like this :
var parsedJson = JObject.Parse(json);
var token = (string)parsedJson["token"];
or
class TokenJsonResult{
public string token {get;set;}
}
var parsedJson = JsonConvert.DeserializeObject<TokenJsonResult>(json);
var token = parsedJson.token;
You can define an anonymous type to use as a template and read the properties like this:
using Newtonsoft.Json;
var input = #"{'token':'eyJhbGciOiJIUzAXRbztetz_WhI'}";
var template = new { token = string.Empty };
var result = JsonConvert.DeserializeAnonymousType(input, template);
Console.WriteLine(result.token);
Output:
eyJhbGciOiJIUzAXRbztetz_WhI

Xamarin: Using HttpClient POST in combination with a dynamic Class

I have some services that require rather complex objects. Every service uses almost the same base object but it needs to be extended for each service.
A simple example:
The Standard Object would be something like:
ContextObject {
params {
Device {
Name: "MyMobileDevice",
ID: 123455691919238
}
}
}
and for my service I need to add some properties under params,
something like:
ContextObject {
params {
Device {
Name: "MyMobileDevice",
ID: 123455691919238
},
requested_employee_id: 112929
}
}
I tried to get this by using JObject and got it working so far but now I cant find a proper example on how to send this object to my server using HttpClient.
Edit:
Here is my full JObject which all Requests need:
public static JObject DefaultContext (string ServiceMethod) {
var Context = new JObject();
Context["version"] = "1.1";
Context["method"] = ServiceMethod;
Context["params"] = JObject.FromObject( new {
Context = JObject.FromObject( new {
User = App.UserSettings.USERNAME,
Password = App.UserSettings.PASSWORD,
SerialNumber = "1234567890", // TODO: use generated id
Locale = "de-DE",
Timestamp = DateTime.Now.ToString("yyyy-MM-ddTHH\\:mm\\:ss.fffzzz"),
Device = JObject.FromObject( new {
DeviceType = "phone",
ProductType = "D6603", // TODO: Get from Device-Info
screen = JObject.FromObject( new {
Density = "xxhdpi", // TODO: Get from Device-Info
resolution = JObject.FromObject( new {
Height = "1920", // TODO: Get from Device-Info
Width = "1080" // TODO: Get from Device-Info
})
}),
version = JObject.FromObject( new {
AppVersion = "myAppVersion", // TODO: Get App-Information LayoutVersion = "1.0"
} )
})
})
});
return mobileContext;
}
For my Requests I need to add parameters under the "params"-Node. Which works with:
mobileContext["params"]["mynewparameter"] = "FOO";
Now I wanted to send this JObject via System.Net.Http-Client to my server with something like this:
var client = new HttpClient ();
client.BaseAddress = new Uri (App.UserSettings.HOST + ":" + App.UserSettings.PORT + App.UserSettings.TYPE);
client.Timeout = 3000;
var context = MyContext.DefaultContext (ServiceMethods.CUSTOMER_LIST_METHOD);
context ["params"] ["myrequestparam"] = "FOO";
var jsonString = JsonConvert.SerializeObject (context);
var responseData = await client.Get???????
Is my general approach correct? How would you do it? Is there a sample on how to handle such dynamic stuff?
I couldn't find a example on how to use httpclient correctly with the Newtonsoft.JSON-Library how far am I from actually working code?

Categories