C# Newtonsoft.Json Deserialize only top level? - c#

I have to work with an API which handles error responses like this:
{
"error": {
"code": 3,
"message": "error message"
}
}
And success respones like this:
{
"data": {
"key": "value"
}
}
Error respones will always contain a code (integer) and a message (string), where as success respones can be different a lot ranging from just a few key-value-pairs to many objects and arrays.
I have created classes for every success "data" section and I can parse them successfully. Now I struggle with the simple part to determine if the response I got is actually an error or a success response.
My Idea was to create these classes:
public class APIResponse
{
[JsonProperty("error")]
public APIResponseError Error { get; set; }
[JsonProperty("data")]
public string Data { get; set; }
}
public class APIResponseError
{
[JsonProperty("code")]
public int Error { get; set; }
[JsonProperty("message")]
public string Message { get; set; }
}
And to serialize to the class APIResponse. This works only for error responses (kinda obvious) as the data responses are more than just a string which the APIResponse.Data actually is. My idea was to not deserialize the data field and just store it as a string in APIResponse.Data. Then, when I check and see that error is null, I would deserialize the APIResponse.Data property with the correct class. But how can I do this?

You can set type of Data property to JToken:
public class APIResponse
{
[JsonProperty("error")]
public APIResponseError Error { get; set; }
[JsonProperty("data")]
public JToken Data { get; set; }
}
And deserialize later with ToObject:
myCorrectResponse.Data.ToObject<ExpectedDataType>()
But I highly doubt that you will be sent any data in case of error response so I would recommend making APIResponse generic (where T could be object, array, etc.):
public class APIResponse<T>
{
[JsonProperty("error")]
public APIResponseError Error { get; set; }
[JsonProperty("data")]
public T Data { get; set; }
}
Which, in case of your example json will be used for example like:
class MyClass
{
[JsonProperty("key")]
public string Key { get; set; }
}
JsonConvert.DeserializeObject<APIResponse<MyClass>>(json);

Related

How to create a .NET Core Serializer for indented Javascript objects

I am trying to serialize JSON objects received from an API in a cli app. I'm having issues understanding how to create the objects in .NET for JSON objects which have an indented structure.
For example, this is fine:
{"status": "ok" }
public class Success
{
public string status { get; set; }
}
But something like this is where I'm stuck and both of the examples from the below return null when the client API receives them.
[
{
"id": "some_uuid_string_1",
"message": "hello"
},
{
"id": "some_uuid_string_2",
"message": "world"
}
]
Attempted solution
public class Received
{
public Dictionary<string,string> received { get; set; }
}
Alternatively I also tried a simpler structure, leaving out the explicit names and just using the IDs and values, which is closer to what my app requires and lets me make smaller requests.
{
"some_uuid_string_1": "hello",
"some_uuid_string_2": "world"
}
For this example I tried this, a list of key value pairs in the form of a dictionary.
public class Message
{
public Dictionary<string,string> message { get; set; }
}
public class Received
{
public List<Message> received { get; set; }
}
How can I create objects in C# for these two structures? One indented with set names and one 'generic' with no set names.
public class MyClass
{
public string id { get; set; }
public string message { get; set; }
}
[
{
"id": "some_uuid_string",
"message": "hello"
},
{
"id": "some_uuid_string",
"message": "world"
}
]
Deserializes to a List<MyClass> or MyClass[]
{
"some_uuid_string_1": "hello",
"some_uuid_string_2": "world"
}
Deserializes to
public class MyClass
{
public string some_uuid_string_1 { get; set; }
public string some_uuid_string_2 { get; set; }
}
or Dictionary<string, string>
The reason your Received class solution didn't work is because it is expecting a JSON property of received, as your class has a property named received, but the JSON does not.
This is the same issue with your Message class. Your class has property message whereas your JSON does not.
create a class
public class MessageId
{
public string id { get; set; }
public string message { get; set; }
}
you can deserialize your json
using Newtonsoft.Json;
var messages=JsonConvert.DeserializeObject<List<MessageId>>(yourJson);

Create corresponding Model for JSON string to get specific value in C#

I have an API that returns a JSON string and I want to parse that JSON string into an object. I tried creating the object but with no luck. Below is the sample JSON string that I want to get the value from. Any idea as to what the class looks like in order to parse that JSON object into an object? My main concern is to get the code which is "platinum" under currentCard.
{
"status" : {
"currentCard" : {
"code" : "platinum"
},
"status" : {
"index" : 0,
"value" : "This is a sample text."
}
}
}
You need to use a website such as https://json2csharp.com/ or use the inbuilt tools in VS Studio (Edit->Paste Special->Paste JSON as classes) which will automatically create classes from JSON.
The above mentioned website suggests the following:
public class CurrentCard
{
public string code { get; set; }
}
public class Status2
{
public int index { get; set; }
public string value { get; set; }
public CurrentCard currentCard { get; set; }
public Status status { get; set; }
}
public class Root
{
public Status status { get; set; }
}
Which you can then deserialise like this:
Root myDeserializedClass = JsonConvert.DeserializeObject<Root>(myJsonResponse);

Finding difficulty in making a model in C#

This question sounds very trivial but I couldn't find it on internet. Let's say I am getting response like following json
{
"status": 1,
"msg": "1 out of 2 Transactions Fetched Successfully",
"transaction_details": {
"f9605b13-c300-4d11-b": {
"mihpayid": "14019310624",
"txnid": "f9605b13-c300-4d11-b",
"mode": "UPI",
"status": "success",
"App_Name": "PhonePe"
},
"546576": {
"mihpayid": "Not Found",
"status": "Not Found"
}
}
}
My problem is How do I make a Model in C# (So that I can deserialize this response)?
I tried this one -
public class TransactionDetails
{
[JsonProperty("txnid")]
public string TransactionId;
[JsonProperty("status")]
public string Status { get; set; }
[JsonProperty("mode")]
public string Mode { get; set; }
[JsonProperty("mihpayid")]
public string MiPayId { get; set; }
[JsonProperty("amt")]
public string amount { get; set; }
[JsonProperty("App_name")]
public string AppName { get; set; }
}
public class ResponseBody
{
[JsonProperty("status")]
public string Status { get; set; }
[JsonProperty("msg")]
public string Message { get; set; }
[JsonProperty("transaction_details")]
public List<TransactionDetails> Transactions { get; set; }
}
I know the problem, Problem is "transaction_details" is not a List, It is object of object.
How do I model that, The number of Keys and name of the Keys are not known!!
Please help me!
and sorry if the question is too trivial.
Any time you are dealing with a JSON structure where the keys are not static (i.e. the key is a unique identifier, date/time, etc.) you will need to use a Dictionary. You will still have the benefit of using a strongly-typed value, and you can perform any validation operations on the key to handle different formats as necessary.

Deserializing a serialized JSON file

I have a JSON file that has been serialized through an API, in which I need to deserialize it to use the data it generated in my code. The issue is that I'm getting an Exception Unhandled error in which I have tried to understand the solution to the error, but I have had a few days off tunnel vision with this issue.
I have tried my best to link my issue with other threads, but have been lost for a few days. I did get some form of sprint finish with setting up a {get { return } } with a property but due to the setup of the code when serializing I couldn't do that. Instead I've tried to put the file outputted in a simple location and tried desalinizing it based on the file location.
ImageModeration image1 = JsonConvert.DeserializeObject<ImageModeration>(File.ReadAllText(#"C:\ModerationOutput.json"));
// deserialize JSON directly from a file
using (StreamReader file = File.OpenText(#"C:\ModerationOutput.json"))
{
JsonSerializer serializer = new JsonSerializer();
ImageModeration image2 = (ImageModeration)serializer.Deserialize(file, typeof(ImageModeration));
}
Here is my json file
[
{
"ImageUrl": "URL",
"ImageModeration": {
"CacheID": "396a972f-79ae-4b31-a54c-0ba3314318fa_637026883058218816",
"Result": false,
"TrackingId": "UKS_ibiza_464a60be-f57d-4ee1-aa37-13d04f151fdd_ContentModerator.F0_4ae15371-36c9-4cb2-8e21-83381a29432c",
"AdultClassificationScore": 0.0048455675132572651,
"IsImageAdultClassified": false,
"RacyClassificationScore": 0.011258091777563095,
"IsImageRacyClassified": false,
"AdvancedInfo": [
{
"Key": "ImageDownloadTimeInMs",
"Value": "37"
},
{
"Key": "ImageSizeInBytes",
"Value": "34854"
}
],
"Status": {
"Code": 3000,
"Description": "OK",
"Exception": null
}
},
"TextDetection": null,
"FaceDetection": null
}
]
This error comes from the first line of code.
Newtonsoft.Json.JsonSerializationException: 'Cannot deserialize the
current JSON array (e.g. [1,2,3]) into type
'convertingJSON.Program+ImageModeration' because the type requires a
JSON object (e.g. {"name":"value"}) to deserialize correctly. To fix
this error either change the JSON to a JSON object (e.g.
{"name":"value"}) or change the deserialized type to an array or a
type that implements a collection interface (e.g. ICollection, IList)
like List that can be deserialized from a JSON array.
JsonArrayAttribute can also be added to the type to force it to
deserialize from a JSON array. Path '', line 1, position 1.'
Specific to your JSON string that you have posted, you can refer to the following code snippet to deserialize your string into its respective components.I am using the Newtonsoft JSON library which is a popular high-performance JSON framework for .NET. A working example can be found at: https://dotnetfiddle.net/RmXNHM
using System;
using Newtonsoft.Json;
using System.Collections.Generic;
public class Program
{
public static void Main()
{
string json=#"[{'ImageUrl':'URL','ImageModeration':{'CacheID':'396a972f-79ae-4b31-a54c-0ba3314318fa_637026883058218816','Result':false,'TrackingId':'UKS_ibiza_464a60be-f57d-4ee1-aa37-13d04f151fdd_ContentModerator.F0_4ae15371-36c9-4cb2-8e21-83381a29432c','AdultClassificationScore':0.004845567513257265,'IsImageAdultClassified':false,'RacyClassificationScore':0.011258091777563095,'IsImageRacyClassified':false,'AdvancedInfo':[{'Key':'ImageDownloadTimeInMs','Value':'37'},{'Key':'ImageSizeInBytes','Value':'34854'}],'Status':{'Code':3000,'Description':'OK','Exception':null}},'TextDetection':null,'FaceDetection':null}]";
var Sresponse = JsonConvert.DeserializeObject<List<RootObject>>(json);
foreach(var value1 in Sresponse)
{
Console.WriteLine(value1.ImageUrl);
Console.WriteLine(value1.ImageModeration.CacheID);
}
}
}
public class AdvancedInfo
{
public string Key { get; set; }
public string Value { get; set; }
}
public class Status
{
public int Code { get; set; }
public string Description { get; set; }
public object Exception { get; set; }
}
public class ImageModeration
{
public string CacheID { get; set; }
public bool Result { get; set; }
public string TrackingId { get; set; }
public double AdultClassificationScore { get; set; }
public bool IsImageAdultClassified { get; set; }
public double RacyClassificationScore { get; set; }
public bool IsImageRacyClassified { get; set; }
public List<AdvancedInfo> AdvancedInfo { get; set; }
public Status Status { get; set; }
}
public class RootObject
{
public string ImageUrl { get; set; }
public ImageModeration ImageModeration { get; set; }
public object TextDetection { get; set; }
public object FaceDetection { get; set; }
}
Output:
URL
396a972f-79ae-4b31-a54c-0ba3314318fa_637026883058218816
Use this site to convert you're JSON to a C# object and then deserialize to it.
According to the error it seems you may have been missing a property i.e. the object does not correspond to the JSON

nested json c# object deserialization

i have the following json string (jsonString)
[
{
"name":"Fruits",
"references":[
{"stream":{"type":"reference","size":"original",id":"1"}},
],
"arts":[
{"stream":{"type":"art","size":"original","id":"4"}},
{"stream":{"type":"art","size":"medium","id":"9"}},
]
}
]
and the following C# objects
class Item
{
public string Name { get; set; }
public List<Stream> References { get; set; }
public List<Stream> Arts { get; set; }
public Item()
{
}
}
class Stream
{
public string Type { get; set; }
public string Size { get; set; }
public string Id { get; set; }
public Stream()
{
}
}
and the following code
Item item = JsonConvert.DeserializeObject<Item>(jsonString);
when I run the code, it creteas the correct number of references and arts, but each stream has null value (type = null, size = null).
is it posible to do this json.net deserializeobject method or should I manually deserialize ?
EDIT: Okay, ignore the previous answer. The problem is that your arrays (references and arts) contain objects which in turn contain the relevant data. Basically you've got one layer of wrapping too many. For example, this JSON works fine:
[
{
"name":"Fruits",
"references":[
{"Type":"reference","Size":"original","Id":"1"},
],
"arts":[
{"Type":"art","Size":"original","id":"4"},
{"type":"art","size":"medium","id":"9"},
]
}
]
If you can't change the JSON, you may need to introduce a new wrapper type into your object model:
public class StreamWrapper
{
public Stream Stream { get; set; }
}
Then make your Item class have List<StreamWrapper> variables instead of List<Stream>. Does that help?

Categories

Resources