How to deserialize dynamic Json objects? - c#

I am currently receiving the following JSON response from my api:
{"Lastname":["ERRLASTNAMEEMPTY"],"Firstname":["ERRFIRSTNAMEEMPTY"]}
Note that the above response is dynamic - i.e sometimes I can have FirstName, sometimes LastName, sometimes both. This response is based on the validation of data.
My question is - is there a way to deserialize this response using JsonSerializer.DeSerialize?
I have tried to use it like this but it does not work:
var errorBody = JsonSerializer.Deserialize<dynamic>(body, serializerOptions);

JsonSerializer.Deserialize<Dictionary<string,string[]>>(body, serializerOptions);

You can work with dynamic JSON objects with JObject like that:
var data = JObject.Parse(body);
And later you are able to access values with data["Lastname"]?.Value<string>(); and such, the way you want.

JsonSerializer.Deserialize<ExpandoObject>(body, serializerOptions);

// introduce a dynamic object from a string :
// {"UrlCheckId":581,"Request":{"JobId":"a531775f-be19-4c78-9717-94aa051f6b23","AuditId":"b05016f5-51c9-48ba-abcc-ec16251439e5","AlertDefinitionId":108,"JobCreated":"2022-05-20T07:09:56.236656+01:00","UrlJobId":0,"BatchJobId":"e46b9454-2f90-407d-9243-c0647cf6502d"},"JobCreated":"2022-05-20T07:10:21.4097268+01:00"}
// ...The UrlCheckId is an int primitive and Request is our UrlCheckJobRequest object.
dynamic msg = JsonConvert.DeserializeObject(message);
// to access an int (primitive) property:
int id = msg.UrlCheckId;
// to access an object, you might have to serialize the request into a string first...
var r = JsonConvert.SerializeObject(msg.Request);
// ... and then deserialize into an object
UrlCheckJobRequest request = JsonConvert.DeserializeObject<UrlCheckJobRequest>(r);

Related

Assert when property has NullValueHandling.Ignore

On my endpoint's response I need to omit a property if its value is null , so I have tagged the prop with the [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] tag.
So, with the tag on the property, this property is not going to be part of the response payload and that's what I want to check/assert on my unit tests, that the property does not appear on my JSON response.
I'm using FluentAssertions as assertion framework and AutoFixture as mock generator.
Why not just assert the response of the HTTP request against a raw JSON? Or use something like where you deserialize the JSON into an object which structure is defined by an anonymous type. See this example on how this works.
I serialized the response of the endpoint, parsed it to a JObject and then validated if the token exists inside that json, something like this:
//Act
var result = await controller.Get(entity.Id);
var objectResult = result as OkObjectResult;
string serializeResponse = JsonConvert.SerializeObject(objectResult.Value,Formatting.Indented);
JObject responseJOject = JObject.Parse(serializeResponse);
//Assert: this is how I checked if the tokens were or not on the json
using (new AssertionScope())
{
responseJOject.ContainsKey("myToken1").Should().BeFalse();
responseJOject.ContainsKey("myToken2").Should().BeFalse();
}
This was based on #dennis-doomen response, I took his advice, but in the opposite way, because all I wanted is to validate if the property was or not inside the response payload (json "body").

Why is JObject.Parse creating an object inside an object from a string?

I have a string value:
var responseString = {"ErrorType":"ServerError","Message":"Incoming data error.","Properties":null}
When I call JObject.Parse(responseString);, I get the following dynamic object:
{{
"ErrorType": "ServerError",
"Message": "Incoming data error.",
"Properties": null
}}
Why is JObject creating a dynamic object that is an object wrapped in an object? I was hoping to write code to access the Message property such as responseMessage.Message as string, but that throws an error.
I just tried the following code in LinqPad:
var responseString = "{\"ErrorType\":\"ServerError\",\"Message\":\"Incoming data error.\",\"Properties\":null}";
dynamic responseMessage = JObject.Parse(responseString);
var msg = (string) responseMessage.Message;
msg.Dump();
In the output, I get the desired Incoming data error. string, so it looks like it is doing what it should. How does your code look? And what version of Json.NET are you using? Also, it is NOT possible to use as to convert to string, as this will return null, since the value is a JToken. You need the explicit cast.

How to return JObject as json object from WebServices

I have a huge dataset of Jobject type created in following format
{
"key_1": {"id":"1", "name":"some1", ....},
"key_2": {"id":"", "name":"some2", .....}
}
I have created such object structure using following code:
JObject res = new JObject();
JObject jo = new JObject();
jo.Add("id", "1");
jo.Add("name", "some1");
res.Add("key_1", jo);
and so on;
I have a webservice method which has return type object and attributes as [WebMethod][ScriptMethod(ResponseFormat = ResponseFormat.Json)]
how to return this data as object in ajax request. I tried res.ToObject<(object)>() //added curely braces around object because of html object tag but it returns empty array collection at client side, but my expectation is get result as mentioned above (a proper object). How should i return res to get desired json output
Edited - thanks Brian
There is a difference between things you CAN do and things you SHOULD do...
The right way to return your JObjects is up to you... create real objects that represent them... create key / value pairs that can be serialized...
What you don't want to do is just write the JSON out to the response... however since that's literally what your asking... here is how you would do it.
[WebMethod]
[ScriptMethod(ResponseFormat = ResponseFormat.Json)]
public void GetObject()
{
string json = GetJsonFromDatabase();
HttpContext.Current.Response.Write(json);
}
Note that your method has to return void and you are writing your json straight out to the response stream. Super dirty... super ugly... please don't do this. You'll also have to manually turn it into an object on the js side.

pulling a python list out of a json object and converting it to something usable in C#

I have a python server that sends a list of strings as a json object to a C# client. On the client end I have this code to deserialize the object:
try
{
var serializer = new System.Web.Script.Serialization.JavaScriptSerializer();
var jsonObject = serializer.DeserializeObject(sr.ReadToEnd());
textBox4.Text = jsonObject.ToString();
}
catch (Exception e){
textBox2.Text = e.ToString();
}
What i'm getting as a result is: "System.Object[]"
Ideally I would like to put the contents of the list into an array.
can anyone point me in the right direction?
You are getting an array of generic objects, however I supose that you don't want this and you prefer getting a more usable result, so:
Create a class with the object's properties (for example: id, name, etc.). You can use this page in order to autogenerate the class.
Then deserialize the input into objects of the class that you have created in the first step, with the following code:
MyNewClass myNewClassList = serializer.Deserialize<MyNewClass>(sr.ReadToEnd());
I hope this can help you
Edit
This is a complete example created with the new information that you tell me in the comments:
var json = "[\"file0\",\"file1\",\"file2\",\"file3\",\"file4\",\"file5\"]";
var serializer = new JavaScriptSerializer();
var files = serializer.Deserialize<List<String>>(json);

Double Label for Json Property C#

I need to pass a Json object to an API, but the API requires the Json properties to have a double label of sorts, such as:
{
"name:id":"1234"
}
However, using Newtonsoft.Json.Linq, I can't get this to format the label exactly. Here is what I've tried so far (which throws an error)
dynamic json= new JObject();
json.name.id = "1234";
Doing
json.id = "1234";
Works just fine. I have also tried
json.name = new JProperty("id", "1234");
Which also throws an error. I have also tried hard coding the json file as a single string and converting that to a JObject, which also threw an error. Is what I'm trying to do possible or am I missing something? Is there another Json package I could use that would support what I want to do?
Use JObject's string indexer notation.
dynamic json = new JObject();
json["name.id"] = "1234";
Since the json is essentially built as a key/value pair, using a string indexer can allow you to overcome atypical property names.
There multiple ways to achieve that.
You can use JsonProperty attribute and specify the property name as name:id like:
class MyClass
{
[JsonProperty("name:id")]
public string Name_Id { get; set; }
}
and then you can do:
MyClass obj = new MyClass();
obj.Name_Id = "1234";
var strJson = JsonConvert.SerializeObject(obj);
and you will get back:
{"name:id":"1234"}

Categories

Resources