Reading a JSON output - c#

Am new to C# and I have an HTTP response which i have converted to a json object via
var result = await response.Content.ReadAsStringAsync();
dynamic jsonResponse = JsonConvert.DeserializeObject(result);
When i Debug.WriteLine((object)jsonResponse); am now getting
{
"status": false,
"data":
{
"message": "Incorrect Username or Password",
"name": "Failed Login"
}
}
Which is as i expect. But the problem comes in reading it i have tried
if ((object)jsonResponse.status != true){ //throws an error
...do stuff
}
The above if statement throws an error
the operand != cannot be applied to operands of type boolean and object
by altering the code and adding
if ((bool)(object)jsonResponse.status != true){ //throws an error
...do stuff
}
the above throws an error
Unable to cast object of type NewtonSoft.Json.Linq.Jvalue to system.boolean
What else do i need to add?
but when i run
Debug.WriteLine((object)jsonResponse.status)
the value is true.
Where am I wrong?

add classes for your response
public class Data
{
public string message { get; set; }
public string name { get; set; }
}
public class LoginResponse
{
public bool status { get; set; }
public Data data { get; set; }
}
then convert response to class
var response = JsonConvert.DeserializeObject<LoginResponse>(result);
and use it
if(!response.status){
//do staff
}

Create classes and deserialize response to it:
public class Data
{
public string message {get;set;}
public string name {get;set;}
}
public class Response
{
public bool status {get;set;}
public Data data {get;set;}
}
var jsonResponse = JsonConvert.DeserializeObject<Response>(result);
if (!jsonResponse.status){
//your code
}

This is not the correct way to read a Json. You can access them one by one, along the way as you come down reading the file.
As in your code below:
{
"status": false,
"data": {
"message": "Incorrect Username or Password",
"name": "Failed Login"
}
}
You will need to access it like this:
JsonObject json = JsonObject.Parse(data);
var statusObject = json.GetNamedBoolean("status");
var dataObject = json.GetNamedObject("data");
var message = dataObject.GetNamedString("message");
var name = dataObject.GetNamedString("name");
// if you need to check whether the `Json` contains the object or not
// check it with
if (dataObject.ContainsKey("message"))
{
// get the value here as above
}

Related

Extract specific data from JSON

I have the following code in my app (using Newton.Json):
var data = JsonConvert.DeserializeObject(responseValue).ToString();
Using the following code:
Console.WriteLine(data);
I get:
{
"result": "some random string goes here",
"error": null,
"id": "1"
}
How do I get the string from the result part of the JSON in the data variable, and put it into its own variable for later use?
If you have a C# class that corresponds to the "shape" of the JSON (same properties with the same data type):
public class ResponseType
{
public string Result { get; set; }
public string Error { get; set; }
public int Id { get; set; }
}
you can do:
ResponseType data = JsonConvert.DeserializeObject<ResponseType>(responseValue);
and then access each property of that class:
string result = data.Result;
This can be done without deserialization.
var json = JObject.Parse(responseValue);
var result = json["result"];
Open namespace.
using Newtonsoft.Json.Linq;

Deserialize JSON property into different class properties

I am receiving API responses from 3rd party that have ambiguous types. For some methods it is:
{"error":{"message":"Resource is already part of this app","status_code":400}}
And on other calls it is:
{"error": "Resource is already part of this app" }
Is it possible to deserialize such responses into something like:
public class Response
{
[JsonProperty("error")]
public string Error { get; set; }
[JsonIgnore] //[JsonProperty("error")]
public ObjectError ObjectError { get; set; }
}
public class ObjectError
{
[JsonProperty("message")]
public string Message { get; set; }
[JsonProperty("status_code")]
public string StatusCode { get; set; }
}
UPDATE
So I have ended up using object as catch all for deserialization.
[JsonProperty("error")]
public object Error { get; set; }
public string ErrorAsString => Error is string ? Error.ToString() : null;
public ObjectError ErrorAsObject => Error is string ? null : Error != null ? JsonConvert.DeserializeObject<ObjectError>(Error.ToString()) : null;
It's not ideal, I know.
You can do this easily using NetwosoftJson. Here you can check on how to deserialize into an object using it.
You could always parse the JSON object and check to see if it has specific fields. For example:
JObject json = JObject.Parse(jsonString);
if(json.HasKey("message"))
{
var result = JsonConvert.DeserializeObject<ObjectError>(jsonString);
// Do some stuff here
}
else
{
var result = JsonConvert.DeserializeObject<Response>(jsonString);
// Do some stuff here
}

c# JsonConvert.DeserializeObject returns null with valid json file

I have the following function:
[HttpPost]
[Route("api/post")]
public void AddFavourite([FromBody]int id) {
var data = GetData(id);
var list = JsonConvert.DeserializeObject<List<VehicleDetail>>(#"C:\FleetStudio\favVehicle.json");
list.Add(data);
var convertedJson = JsonConvert.SerializeObject(list, Formatting.Indented);
}
My list is null however and returns the following error:
Newtonsoft.Json.JsonReaderException: 'Unexpected character encountered
while parsing value: C. Path '', line 0, position 0.'
My data.json looks like the following (and passes the test on https://jsonlint.com/)
[
{
"Name": "mocksson",
"Id": 32,
"Alarm": null,
"Signalinfo": null,
"Position": null
}
]
and my VehicleDetail class look like the following:
public class VehicleDetailsClass
{
public string Name { get; set; }
public int Id { get; set; }
public List<Alarms> Alarm { get; set; }
public List<SignalInfo> Signalinfo { get; set; }
public Position Position { get; set; }
}
I don't see in any way how the list can be null. There is nothing exciting to this line of code, and it still manages to crash. Does anyone see where it all goes wrong?
use File.ReadAllText to read your jsonData from file in disk, then pass the jsonData be parameter in JsonConvert.DeserializeObject
JsonConvert.DeserializeObject method parses json string instead of filePath.
string jsonDATA = File.ReadAllText(#"C:\FleetStudio\favVehicle.json")
var list = JsonConvert.DeserializeObject<List<VehicleDetail>>(jsonDATA);

Extract value for key from json c#

I have the following Json (is a file attached to the project):
{
"Errors": {
"NoCountry": {
"MSG": "The CountryCode field is required.",
"Description": "Error encountered when Country parameter is missing from the request"
},
"NoLOI": {
"MSG": "Validation failed: \r\n -- LengthOfInterview cannot be empty"
"Description": "Error encountered when LOI parameter is missing from the request"
}
}
}
I need to extract the values for e.g. Errors.NoCompletes.MSG in order to use it in an assert to compare it with an output that i get from the API.
Till now i tried to create a dictionary that looks like this:
public class ErrorsDictionary
{
public string MSG;
public string Description;
}
public class DicRoot
{
public Dictionary<string, ErrorsDictionary> Errors { set; get; }
}
And use it like this:
DicRoot Json = JsonConvert.DeserializeObject<DicRoot>(File.ReadAllText(#"c:\users\banu_\source\repos\TestJsonLib\TestJsonLib\Json\ErrorMSG.json"));
foreach (var f in Json.Errors)
{
Console.WriteLine("Nume={0} Mesaj={1} Description={2}",f.Key, f.Value.MSG, f.Value.Description);
}
The problem is that i cannot figure out, how can i extract a specific value, like what i said above for Errors.NoLOI.MSG, in order to be able to use it in an assert like Assert.Equals(ex, MyParam);
You can also use JsonPath, anonymous types and string interpolation if you like:
JObject obj = JObject.Parse(json);
var errors = obj
.SelectTokens("$.Errors.*")
.ToDictionary(
e => ((JProperty)e.Parent).Name,
e => new { Msg = e["MSG"], Descr = e["Description"] });
foreach (var e in errors)
{
Console.WriteLine($"Nume={e.Key} Mesaj={e.Value.Msg} Description={e.Value.Descr}");
}
I think what you are asking for is this?
DicRoot dict = JsonConvert.DeserializeObject<DicRoot>(File.ReadAllText("foo.json"));
string msg = dict["NoLOI"].MSG;
I know this looks like a bit working around. However, it's working.
class Program
{
static void Main(string[] args)
{
string json = "{\"Errors\": {\"NoCountry\": {\"MSG\": \"The CountryCode field is required.\",\"Description\": \"Error encountered when Country parameter is missing from the request\"},\"NoLOI\": {\"MSG\": \"Validation failed: \r\n -- LengthOfInterview cannot be empty\", \"Description\": \"Error encountered when LOI parameter is missing from the request\"},}}";
var Json = JsonConvert.DeserializeObject<ErrorsClass>(json);
var obj = JsonConvert.DeserializeObject<Dictionary<string, ErrorsDictionary>>(Json.Errors.ToString());
foreach (var f in obj)
{
Console.WriteLine("Nume={0} Mesaj={1} Description={2}", f.Key, f.Value.MSG, f.Value.Description);
}
Console.Read();
}
}
public class ErrorsDictionary
{
public string MSG { get; set; }
public string Description { get; set; }
}
public class DicRoot
{
public Dictionary<string, ErrorsDictionary> ErrorsDic { set; get; }
}
class ErrorsClass
{
public object Errors { get; set; }
}
Output:
Nume=NoCountry Mesaj=The CountryCode field is required. Description=Error encountered when Country parameter is missing from the request
Nume=NoLOI Mesaj=Validation failed:
-- LengthOfInterview cannot be empty Description=Error encountered when LOI parameter is missing from the request
You can use Newtonsoft.json NuGet. Try this
var files = JObject.Parse(YourJson);
var recList = files.SelectTokens("$..Errors").ToList();
foreach (JProperty prop in recList.Children())
{
string key = prop.Name.ToString();
string value = prop.Value.ToString();
//Do your stuffs here
}

Getting an error in my Web API serialization

I have a WebApi with several controllers which return different results. For example, one controller returned an IEnumerable<Foo>, another a Bar, another an IEnumerable of IEnumerable etc., and all I had to do was:
return Ok(thething)
and everything worked fine, even complicated nested objects were serialized with no problem.
Now, The client asked that all results be returned in a Wrapper:
public class Wrapper
{
public bool Success { get; set; }
public int ErrorCode { get; set; }
public String ErrorMessage { get; set; }
public String Referrer { get; set; }
public Object Payload { get; set; }
}
Thought it would be trivial, but when I try to return it from the controller:
return Ok(new Wrapper { Success = true, Referrer = "me", Payload = thething)
I get a serialization error:
The 'ObjectContent`1' type failed to serialize the response body for content type 'application/xml; charset=utf-8'.
The inner exception message is:
'System.Linq.Enumerable+WhereSelectListIterator2[[EPiServer.Find.Api.SearchHit1[[DGTNext.Api.Data.Entities.ProductSummary,
DGTNext.Api.Entities, Version=1.0.0.0, Culture=neutral,
PublicKeyToken=null]], EPiServer.Find, Version=9.6.0.3185,
Culture=neutral,
PublicKeyToken=8fe83dea738b45b7],[DGTNext.Api.Data.Entities.ProductSummary,
DGTNext.Api.Entities, Version=1.0.0.0, Culture=neutral,
PublicKeyToken=null]]' with data contract name
'ArrayOfProductSummary:http://schemas.datacontract.org/2004/07/DGTNext.Api.Data.Entities'
is not expected. Consider using a DataContractResolver if you are
using DataContractSerializer or add any types not known statically to
the list of known types - for example, by using the KnownTypeAttribute
attribute or by adding them to the list of known types passed to the
serializer.
What am I doing wrong? Why did the Ok() function seem to be handle any object before, but has problems now?
Thanks.
Edit: as requested, a simple example of something causing the error:
class Foo
{
public int AnInt { get; set; }
}
public IHttpActionResult Get()
{
return Ok(new Wrapper { Success = true, Referrer = "me", Payload = new Foo { AnInt = 7 } });
}
Edit #2: well, I came up with kind of a solution, but it still raises some questions.
I made my Wrapper generic in the type of the payload.
public class Wrapper<T>
{
public bool Success { get; set; }
public int ErrorCode { get; set; }
public String ErrorMessage { get; set; }
public String Referrer { get; set; }
public T Payload { get; set; }
}
So now, this works:
public IHttpActionResult Get()
{
List<Foo> foos = new List<Foo>();
foos.Add(new Foo { AnInt = 7 });
foos.Add(new Foo { AnInt = 8 });
return Ok(new Wrapper<IEnumerable<Foo>> { Success = true, Referrer = "me", Payload = foos });
}
It returns:
{
"Success": true,
"ErrorCode": 0,
"ErrorMessage": null,
"Referrer": "me",
"Payload": [ { "AnInt": 7 }, { "AnInt": 8 } ]
}
And my "real" call:
public IHttpActionResult Get()
{
IEnumerable<ProductSummary> prods = db.getProductSummaries(shopId, culture, queryParams, paging);
return Ok(new Wrapper<IEnumerable<ProductSummary>> { Success = true, Referrer = "me", Payload = prods });
}
returns:
<WrapperOfArrayOfProductSummaryzc2y5_Pnl>
<ErrorCode>0</ErrorCode>
<ErrorMessage i:nil="true"/>
<Payload>
<d2p1:ProductSummary>
<d2p1:Culture i:nil="true"/>
<d2p1:Guid i:nil="true"/>
<d2p1:Id>2</d2p1:Id>
<d2p1:Name>Letto Asia</d2p1:Name>
<d2p1:ambient>
<d2p1:Id>1073741838</d2p1:Id>
<d2p1:Name>notte</d2p1:Name>
</d2p1:ambient>
etc.
So not bad, but this raises two questions:
To test the webapi, I'm calling it by putting an URL in the Firefox address bar and looking an the results in the browser. Why in the world does the first call return Json, and the second XML? As far as I know I'm just using default everything.
Why is the XML now adding that namespace to all the element names? Can I prevent this? When I was just returning the same thing without the wrapper, this didn't happen.
Add this code to global.asax below on Application_Start:
Update from .Ignore to .Serialize. It must work.
GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Serialize;
GlobalConfiguration.Configuration.Formatters.Remove(GlobalConfiguration.Configuration.Formatters.XmlFormatter);
or you may look at this answer

Categories