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

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

Related

Unable to deserialize the JSON Data

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

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

Cosmos DB Azure Table API oData Authentication REST / C#?

I'm trying to access Azure Cosmos DB using Table API.
The challenge is, despite creating SharedKeyLite, server is still returning Unauthorized - seems like SharedKeyLite is not supported or I'm generating the signature or headers wrong.
Here is the code
static readonly string storageAccountName = "accountName";
static readonly string storageAccountKey = "xxxx";
static readonly string uri = "https://accountName.table.cosmosdb.azure.com/Contacts()";
static readonly string utc_date = DateTime.UtcNow.ToString("r");
static void Main(string[] args)
{
Console.WriteLine(GetResult().Result);
}
static async Task<string> GetResult()
{
// Set this to whatever payload you desire. Ours is null because
// we're not passing anything in.
Byte[] requestPayload = null;
var requestDateString = DateTime.UtcNow.ToString("R", CultureInfo.InvariantCulture);
var requestUri = new Uri(uri);
DateTime now = DateTime.UtcNow;
//Instantiate the request message with a null payload.
using (var httpRequestMessage = new HttpRequestMessage(HttpMethod.Get, uri)
{ Content = (requestPayload == null) ? null : new ByteArrayContent(requestPayload) })
{
ConstructHeaders(httpRequestMessage.Headers, requestDateString);
string authorizationHeader = GenerateSharedKeyLite(storageAccountKey, storageAccountName, uri,requestDateString);
httpRequestMessage.Headers.Authorization = new AuthenticationHeaderValue("SharedKeyLite", authorizationHeader);
// Send the request.
using (HttpResponseMessage httpResponseMessage = await new HttpClient().SendAsync(httpRequestMessage))
{
string json = await httpResponseMessage.Content.ReadAsStringAsync();
return json;
}
}
}
These are the headers I"m adding, expansion of ConstructHeaders method.
Refer this link for request parameters
//Construct the headers
static void ConstructHeaders(HttpRequestHeaders headers, string now)
{
headers.Add("x-ms-date", now);
headers.Add("x-ms-version", "2017-04-17");
// If you need any additional headers, add them here before creating
// the authorization header.
headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
if (headers.Contains("DataServiceVersion"))
headers.Remove("DataServiceVersion");
headers.Add("DataServiceVersion", "3.0;NetFx");
if (headers.Contains("MaxDataServiceVersion"))
headers.Remove("MaxDataServiceVersion");
headers.Add("MaxDataServiceVersion", "3.0;NetFx");
}
And this is the method that creates the SharedKeyLite
//Created Shared Key Lite
static string GenerateSharedKeyLite(string accessKey, string account, string url, string date)
{
var uri = new Uri(url);
var canonicalizedResourceString = uri.PathAndQuery;
var queryStart = canonicalizedResourceString.IndexOf('?');
if (queryStart > -1)
{
if (queryStart < canonicalizedResourceString.Length - 1)
{
var path = canonicalizedResourceString.Substring(0, queryStart);
var parameters = HttpUtility.ParseQueryString(canonicalizedResourceString.Substring(queryStart + 1));
var sb = new StringBuilder();
foreach (var keyOri in parameters.Keys)
{
var value = parameters[keyOri];
var key = keyOri.ToLowerInvariant();
sb.Append("\n");
sb.Append(key);
sb.Append(":");
sb.Append(value);
}
canonicalizedResourceString = canonicalizedResourceString + sb.ToString();
}
else
{
canonicalizedResourceString = canonicalizedResourceString.Substring(0, canonicalizedResourceString.Length - 1);
}
}
canonicalizedResourceString = $"/{account}{canonicalizedResourceString}";
var stringToSign = $"{date}\n{canonicalizedResourceString}";
var signedSignature = string.Empty;
using (var hmac = new HMACSHA256(Convert.FromBase64String(accessKey)))
{
var outputBytes = hmac.ComputeHash(Encoding.UTF8.GetBytes(stringToSign));
var signature = Convert.ToBase64String(outputBytes);
return $"{account}:{signature}";
}
}
Any Help? Ideally I want to perform the odata query using simple.odata, but first trying to make this work using HttpClient
Just copy your code and it works on my side. If you haven't modified your code, please make sure your storageAccountName and storageAccountKey are correct.
BTW, in method GenerateSharedKeyLite there's no need to add query parameters to canonicalizedResourceString for entity operation. You only need to add comp if you want to operate component info for table or service. See constructing-the-canonicalized-resource-string.
The query string should include the question mark and the comp parameter (for example, ?comp=metadata). No other parameters should be included on the query string.

Categories