Reading values from dynamic JSON - c#

Something is making my head in,
I have an API that returns me JSON, the JSON can have a slight different format depending on the endpoint is sending it.
Example.
{
"PayLoad": {
"Method1": [
{
"TimeStamp": "2020-06-03T13:25:25",
"Id": 4235411
}
],
"Timestamp": "2020-06-03T13:26:57.1316371+00:00",
"Signature": "113af0a218b0497ff6f160fcd1b13a7b",
"Hookid": "526ed776-2l71-4c2a-b11f-de8cb2057b1c"
}
}
So what I am looking for is to have returned
Method : Method1
TimeStamp: 2020-06-03T13:25:25
id: 4235411
Signature: 113af0a218b0497ff6f160fcd1b13a7b
HookID: 526ed776-2l71-4c2a-b11f-de8cb2057b1c
Can someone please give me an hint?
I've tried a bunch of code examples I've seen, and can't make it work.

Without getting more information it is hard to know exactly what you are asking but I would look at the examples in JSON.net's Linq to JSON documentation:
https://www.newtonsoft.com/json/help/html/LINQtoJSON.htm
https://www.newtonsoft.com/json/help/html/QueryingLINQtoJSON.htm
string json = #"
{
'PayLoad': {
'Method1':
[
{
'TimeStamp': '2020-06-03T13:25:25',
'Id': 4235411
}
],
'Timestamp': '2020-06-03T13:26:57.1316371+00:00',
'Signature': '113af0a218b0497ff6f160fcd1b13a7b',
'Hookid': '526ed776-2l71-4c2a-b11f-de8cb2057b1c'
}
}";
JObject obj = JObject.Parse(json);
string method1_timestamp = (string)obj["PayLoad"]["Method1"][0]["TimeStamp"];
// "2020-06-03T13:25:25"
// Use technique to parse out other values if needed

You can try creating a class compatible with the expected JSON format:
public class Payload
{
public int Id {get; set;}
public Guid HookID {get; set;}
public string Signature {get; set;}
public Method[] Methods {get; set;}
public DateTime TimeStamp {get; set;}
}
public class Method
{
public int Id {get; set;}
public DateTime TimeStamp{get; set;}
}
Than you can parse the JSON data as a Payload object.
Payload payload = JsonConvert.DeserializeObject<Payload>(json);

Related

c# Web api nested json field change dynamically

I need to return a json object from my web api. The problem is there is a nested object. in that object column name changed dynamically and also nested object has only cursive bracket. Sample json given below. Any one know how to solve this issue please help.
[
{
src: 'https://www.test.com/line.jpg',
screen: 'PLAYLIST_SCREEN',
data: {
playlist_id: '751becbe-5546-4728-8738-e96238be4749'
}
},
{
src: 'https://www.test.com/linet-2.jpg',
screen: 'VIDEO_SCREEN',
data: {
video_id: '40541a11-e29d-4852-91c8-c2aac76d64c9'
}
},
{
src: 'https://www.test.com/line_3xl.jpg?impolicy=HomeHero',
screen: 'SEARCH_SCREEN',
data: {
query: 'برنامج صباح الخير يا كويت'
}
}
]
Assuming data is coming from a C# object, you can use this attribute to skip serialization of any properties that are null:
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
Here is an example of what data might look like in C#:
public class data
{
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
[JsonPropertyName("playlist_id")]
public string? PlaylistId { get; set; }
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
[JsonPropertyName("video_id")]
public string? VideoId { get; set; }
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
[JsonPropertyName("query")]
public string? Query { get; set; }
};
The Microsoft documentation has more examples of usage.

Is there a way to Serialize Json that contains a field that contains more json as a string to XML

I receive Json-data from an external source. I need to convert the Json messages to XML.
This is relatively simple using the NewtonSoft library:
var placeHolder = $"{{\"Data\": {jsonContent} }} ";
var xmlNode = JsonConvert.DeserializeXmlNode(placeHolder, "Root").OuterXml;
var doc = new XmlDocument();
doc.LoadXml(xmlNode);
There is one little odd thing about the Json that I receive that breaks this entire process.
The Json looks like this:
[
{
"Type": "Application",
"Object": {
"Duration": 2,
"Request": {
"authReference": "..",
"IdEnrolment": {
"username": "test",
"password": "***",
"createNewUser": false
}
},
"Type": "XXX.SomeController",
"Logs": [
],
"Method": "IdEnrolments",
"Response": {
"IdUsername": null,
"result": {
"resultCode": 0,
"resultTitle": null,
"resultMessage": null
}
}
}
},
{
"Type": "Proxy",
"Object": {
"Assembly": null,
"Policy": null,
"Cache": null,
"Duration": 516,
"Request": "{\"AuthenticateUserRequest\":{\"EnterpriseContext\":{\"ContextInfo\":{\"#xmlns\":\"http://example.xom\",\"ProcessContextId\":\"adad\",\"ExecutionContextId\":\"adac\"}\"}}",
"Type": "https://someserver/services/ent/informationandtechnologymanagement/company/v1",
"Logs": [
],
"Method": "AuthenticateUser",
"Response": "{\"AuthenticateUserResponse\":{\"EnterpriseContext\":{\"ContextInfo\":{\"#xmlns\":\"http://example.com\",\"ProcessContextId\":\"adad\",\"ExecutionContextId\":\"adad\"}}}}"
}
}
]
The first object in the array is perfect and serializes correctly. The second object in the array causes chaos (understandably). The Request and Response fields for this object are actually Strings and they contain the JSON code.
Is there a way to deserialize this properly? I realize that it is a lot to ask from a library to be flexible enough to do this - but I'm just a little stumped at how to use this.
All the messages I receive look roughly the same - but specifically the content of the Request and Response objects are different depending on the specific request/response.
The guys who built this do not have any sort of Schema or contract in place, other than the fact that they send Json text around and they seem unwilling or unable to change how the Json is created.
Any advice will really be appreciated.
Note: It seems that the behavior isn't random. Whether I get a proper object or a string is determined by the attribute: "Type": "Application". There are many different "Types" - and some are properly serialized and others not.... Aaarrggghhh!!!! Frustration !!!!
Your JSON is bricked in root/Type:Proxy/Object/ the Request-nesting is malformed:
"Request": "{\"AuthenticateUserRequest\":{\"EnterpriseContext\":{\"ContextInfo\":{\"#xmlns\":\"http://example.xom\",\"ProcessContextId\":\"adad\",\"ExecutionContextId\":\"adac\"}\"}}",
Here you have 4 curly brackets open, but only 3 that close.
The JSON you have to handle is very very irregular and bad, so that you just have to deconstuct all of that into C# interfaces, classes, and structs like so:
#region Fields
enum JsonObjType
{
Application,
Proxy,
SomeController,
}
#endregion
#region Classes
// Application
public class AppObj : JsonObjMaster
{
public readonly JsonObjType Type_Ind {get;}
public int Duration {get; set;}
public AppRequest Request {get; set;}
public AppObjController Controller {get; set;}
//you need a default constuctor for classes, cause else no json parser will work with them
public AppObj()
{
Type_Ind = JsonObjType.Application;
Duration = 0;
AppResult = String.Empty;
Request = new AppRequest();
Controller = new AppObjController();
}
}
public class AppObjController : JsonObjSlave
{
public readonly JsonObjType Type_Ind {get;}
public string[] Logs {get; set;}
public Func</*whatever is supposed to be here*/> Method {get; set;}
public AppResult Result {get; set;}
public AppObjController()
{
Type_Ind = JsonObjType.SomeController;
Log = Array.Empty<string>();
Method = (/*whatever is supposed to be here*/) => null; //may need to change depending on what the function is for
Result = new AppResult();
}
}
// Proxy
public class ProxyObj : JsonObjMaster
{
public readonly JsonObjType Type_Ind {get;}
public int Duration {get; set;}
public string Assembly {get; set;} //I am assuming strings here since no type is supplied
public string Policy {get; set;}
public string Cache {get; set;}
public string Request {get; set;}
public string Type {get; set;}
public string[] Logs {get; set;}
public Func</*whatever is supposed to be here*/> Method {get; set}
public string Response {get; set;}
public ProxyObj()
{
Type_Ind = JsonObjType.Proxy;
Duration = 0; //not needed but to stay consistent
Assembly = String.Empty();
Policy = String.Empty();
Cache = String.Empty();
Request = String.Empty();
Type = String.Empty();
Logs = Array.Empty<string>();
Method = (/*whatever is supposed to be here*/) => null; //may need to change depending on what the function is for
Response = String.Empty();
}
}
#endregion
#region Structs
// Interfaces
public interface JsonObjMaster
{
public readonly JsonObjType Type_Ind {get;}
public int Duration {get; set;}
}
public interface JsonObjSlave
{
public readonly JsonObjType Type_Ind {get;}
}
// Structs
public struct IdEnrolment
{
public string Username {get; set;}
public string Password {get; set;}
public bool CreateNewUser {get; set;}
}
public struct AppResult
{
public int Code {get; set;}
public string Title {get; set;}
public string Message {get; set;}
}
public struct AppRequest
{
public string AuthRefernece {get; set;}
public IdEnrolment {get; set;}
}
#endregion
In order to load the JSON into the classes you now need to supply the parer with the names of the C# object properties in the context of the JSON file so that the parser can link them. This can look something like this:
[MyJsonparser.JsonName("Type")]
public string Type {get; set;}
But it is highly dependant on the JSON lib you're using, so you need to look it up in their docs.
If you can sucsessfully convert the JSON fuckery that someone (hopefully not you) did into C# objects you can then resolve the JSON strings that are left over by moving to another layer of classes and structs, which you can then use for processing.
Now after you have that JSON as C# ocjects you can easily serialize it to XML but sadly because of how bad the JSON is implemented you wont be able to do it automatically without using C# objects as a meta-medium.

How to parse my Json Response String in C# [duplicate]

This question already has answers here:
Parse Json string in C#
(5 answers)
Closed 6 years ago.
This is the JSON Response I'm getting,I unable to parse,Please help me.
{
"features": [{
"attributes": {
"OBJECTID": 1,
"schcd": "29030300431",
"schnm": "UNAIDED GENITALIA LIPS DALMATIA RS"
},
"geometry": {
"x": 8449476.63052563,
"y": 1845072.4204768054
}
}]
}
To parse a JSON you will most likely need a extern library like JSON.Net or something similar.
Then you need to create a classes (a wrapper) with properties that match your JSON String and deserialize the string into that object.
When you create the wrapper class into which you want to deserialize your JSON String you have be careful to name the properties the same way they are named in the JSON String.
Example:
public class MyObject {
public List <Feature> Features {get;set;}
}
public class Feature {
public MyAttributes Attributes {get;set; }
public Geometries Geometries {get;set; }
}
public class MyAttributes {
public int ObjectID {get;set;}
public string Schcd {get;set;}
public string Schnm {get;set;}
}
public class Geometries {
public double X {get;set;}
public double Y {get;set;}
}
Then just call the deserialisation function of the JSON library:
var myObject = JsonConvert.DeserializeObject<MyObject>(jsonString);
To access a property like the Object ID then you just call:
myObject.Features[0].Attributes.ObjectId;
If you're ok with using dynamic you can do like this
var json = "{ \"features\" : [ { \"attributes\": { \"OBJECTID\": 1, \"schcd\": \"29030300431\", \"schnm\": \"UNAIDED GENITALIA LIPS DALMATIA RS\" }, \"geometry\": { \"x\": 8449476.63052563, \"y\": 1845072.4204768054 } } ] }";
dynamic obj = JsonConvert.DeserializeObject(json);
var objectId = obj.features[0].attributes.OBJECTID;
It uses Newtonsoft.Json, which can be installed with Nuget from here.
Install-Package Newtonsoft.Json
Be aware that this doesn't do any null-checks, and simply assumes that it's the first object in features that you want. But it's simple and doesn't require you to create any models.
If you want to use a more complete model I would go for the answer provided by Bojan B or j0ey_wh.
Here is an answer that might get you started Deserialize JSON with C#
I like more the solution from NewtonSoft: Newtonsoft JSON Deserialize
You can use their JsonConverter to simply serialize/deserialize objects
Here's a simple example:
You first need classes that match the structure of your JSON:
public class MyCoolClass
{
public IEnumerable<Feature> features {get; set;}
}
public class Feature
{
public Attributes Attributes {get; set;}
public Geometry Geometry {get; set;}
}
public class Attributes
{
public int ObjectId {get; set;}
public string Schcd {get; set;}
public string Schnm {get; set;}
}
public class Geometry
{
public double X {get; set;}
public double Y {get; set;}
}
Then you just use JsonConverter (JSON.Net) like this:
MyCoolClass tmp = JsonConvert.DeserializeObject<MyCoolClass>(jsonStringThatYouGot);

Deserializing nested JSON arrays using RestSharp

I'm trying to deserialize the following JSON response using RestSharp. I have tried various model structures to extract the data to no avail. I keep getting tripped up on the nested arrays.
I do not have control over the service, so I can't change the format.
JSON Format:
[
{
"results": 19,
"statuscode": 200,
},
[
{
"id": 24,
"name": "bob"
},
{
"id": 82,
"name": "alice"
}
]
]
Using this model, I've been able to pull the data from the first object, but that's all. I'm not sure how exactly to read through the array that comes after the object.
public class Info
{
public int results { get; set; }
public int statuscode { get; set; }
}
Example deseralization:
var deserializer = new JsonDeserializer();
var wat = deserializer.Deserialize<List<List<Info>>>(response);
Am I just completely missing something here or are my only options to write a custom deserializer and/or use something like JSON.NET?
The problem is that your JSON array is exceptionally polymorphic: its first element is an object, and its second element is an array of objects. A more natural way to represent this would have been as a JSON object with two named properties -- but that's not what you have been given. Deserializing this directly to a c# POCO with two named properties in a single step with any serializer is going to be tricky since the JSON data model is quite different than your desired data model. Instead, it may be easiest to deserialize to an intermediate representation and convert. Luckily RestSharp has appropriate intermediate classes JsonObject and JsonArray.
Thus, if you want to deserialize to the following classes:
public class Info
{
public int results { get; set; }
public int statuscode { get; set; }
}
public class IdAndName
{
public int id { get; set; }
public string name { get; set; }
}
public class ResponseContent
{
public Info Info { get; set; }
public List<IdAndName> Data { get; set; }
}
You can do:
var array = (JsonArray)SimpleJson.DeserializeObject(response.Content);
var responseContent = (array == null ? (ResponseContent)null : new ResponseContent()
{
Info = array.OfType<JsonObject>().Select(o => SimpleJson.DeserializeObject<Info>(o.ToString())).FirstOrDefault(),
Data = array.OfType<JsonArray>().SelectMany(a => SimpleJson.DeserializeObject<List<IdAndName>>(a.ToString())).ToList()
});

Json.Net - How to deserialize only if types are matching

I have a class like this:
public class Event
{
[JsonProperty(PropertyName = "_id")]
public string Id { get; set; }
[JsonProperty(PropertyName = "status"]
public string Status { get; set; }
}
I am receiving JSON that looks like this:
[
{
"_id": 4,
"status": "started"
},
{
"_id": 117841261,
"status": {
"_statusid": 1,
"date": "01.01.2015"
}
}
]
Please be aware: in the first object, the status field is a string. In the second object, it's an object. In my object it's a string property. I want to parse it whenever the status field is a string. I'm okay with skipping it when it's an object like in the second object.
I have tried changing the defaultValueHanding options in the JsonProperty attribute, but it didn't help. Is there any way to achieve this?
I have solved this problem chaging property type to dynamic. So it's deserializing everytime with no problem and i am using it only when i need it.
Now my model looks like this:
public class Event
{
[JsonProperty(PropertyName = "_id")]
public string Id { get; set; }
[JsonProperty(PropertyName = "status"]
public dynamic Status { get; set; }
}
As Brian Rogers pointed out, custom converter can be found here:
How to deserialize a JSON property that can be two different data types using Json.NET

Categories