Suppose I have JSON like this, how can I model my class for deserialization?
I have no problems to model class for standard attribute like "dummy" or normal arrays, but in this case, my "links" array is a list of items with different name ("addons", "conditions", "conversion", etc.).
"dummy": "1",
"links": {
"addons": {
"href": "/16071d9f-efec-4282-a42e-a495eea76ae0/offers/031C9E47-4802-4248-838E-778FB1D2CC05/addons",
"method": "GET"
},
"conditions": {
"href": "/16071d9f-efec-4282-a42e-a495eea76ae0/offers/031C9E47-4802-4248-838E-778FB1D2CC05/conditions",
"method": "GET"
},
"conversions": {
"href": "/16071d9f-efec-4282-a42e-a495eea76ae0/offers/031C9E47-4802-4248-838E-778FB1D2CC05/conversions",
"method": "GET"
},
"list_prices": {
"href": "/16071d9f-efec-4282-a42e-a495eea76ae0/offers/031C9E47-4802-4248-838E-778FB1D2CC05/list-prices",
"method": "GET"
},
"mutual_exclusion": {
"href": "/16071d9f-efec-4282-a42e-a495eea76ae0/offers/031C9E47-4802-4248-838E-778FB1D2CC05/mutually-exclusive-offers",
"method": "GET"
},
"prerequisites": {
"href": "/16071d9f-efec-4282-a42e-a495eea76ae0/offers/031C9E47-4802-4248-838E-778FB1D2CC05/prerequisites",
"method": "GET"
},
"product": {
"href": "/16071d9f-efec-4282-a42e-a495eea76ae0/products/f245ecc8-75af-4f8e-b61f-27d8114de5f3",
"method": "GET"
}
},
Assuming you are specifically looking for the set of LinkTypes if you will, in your JSON, could you use something like the following, and execute the Deserialize on the RootObject?
Working dotNet Fiddle: https://dotnetfiddle.net/ZWSlK4
Check out the output on the Console pane on the fiddle page.
public class Link
{
public string Href { get; set; }
public string Method { get; set; }
}
public class Links
{
[JsonProperty("addons")]
public Link Addons { get; set; }
[JsonProperty("conditions")]
public Link Conditions { get; set; }
[JsonProperty("conversions")]
public Link Conversions { get; set; }
[JsonProperty("list_prices")]
public Link ListPrices { get; set; }
[JsonProperty("mutual_exclusion")]
public Link MutualExclusion { get; set; }
[JsonProperty("prerequisites")]
public Link Prerequisites { get; set; }
[JsonProperty("product")]
public Link Product { get; set; }
}
public class RootObject
{
public string dummy { get; set; }
public Links links { get; set; }
}
and then execute the Deserializer like so.
var myDummyLinksList = JsonConvert.DeserializeObject<RootObject>(jsonText);
where jsonText contains the json string you have listed in your example:
However, if you List of links objects is dynamic and the number of objects inside varies and you need to capture all of them, then you might have to write a custom Converter that inherits from the JsonConverter object. then use the answer that #mfarouk has posted.
I forked my dotNet Fiddle and implemented his solution and it works like a boss for the dynamic case!
Working dotNet Fiddle (dynamic case): https://dotnetfiddle.net/7bFcNM
Hope this helps!
the links attribute could be parsed as key, value dictionary , the class can be like
public class JSONClass
{
public string dummy { get; set; }
public Dictionary<string, Link> links;
public class Link
{
public string Href { get; set; }
public string Method { get; set; }
}
}
then de-serialized as
var obj = Newtonsoft.Json.JsonConvert.DeserializeObject<JSONClass>(JSON);
Related
I have not found any code examples how to write Cognito trigger in C#. I am particularly interested in pre authentication trigger.
Right now I have the following Lambda function which is set as a pre authentication trigger in Cognito:
public APIGatewayProxyResponse ExampleTrigger(APIGatewayProxyRequest request, ILambdaContext context)
{
context.Logger.LogLine("trigger called");
return new APIGatewayProxyResponse
{
StatusCode = (int)HttpStatusCode.OK
};
}
However, I receive this error:
{code: "InvalidLambdaResponseException", name: "InvalidLambdaResponseException", message: "Unrecognizable lambda output"}
I think this error is caused because the type APIGatewayProxyResponse is not correct. But what is the correct type?
According to the documentation, handler should expect an object, which represents the following JSON ( including common parameters) :
{
"version": "string",
"triggerSource": "string",
"region": "string",
"userPoolId": "string",
"userName": "string",
"callerContext": {
"awsSdkVersion": "string",
"clientId": "string"
},
"request": {
"userAttributes": {
"string": "string",
. . .
},
"validationData": {
"string": "string",
. . .
},
"userNotFound": boolean
},
"response": {}
}
Also lambda handler should return the same type of object.
Since you are working with C#, probably you can use following classes to deserialize the object. So instead of both APIGatewayProxyRequest and APIGatewayProxyResponse, please use below mentioned Event Type.
public class Event
{
[JsonPropertyName("version")]
public string Version { get; set; }
[JsonPropertyName("region")]
public string Region { get; set; }
[JsonPropertyName("userPoolId")]
public string UserPoolId { get; set; }
[JsonPropertyName("userName")]
public string UserName { get; set; }
[JsonPropertyName("callerContext")]
public CallerContext CallerContext { get; set; }
[JsonPropertyName("triggerSource")]
public string TriggerSource { get; set; }
[JsonPropertyName("request")]
public Request Request { get; set; }
[JsonPropertyName("response")]
public Response Response { get; set; }
}
public class CallerContext
{
[JsonPropertyName("awsSdkVersion")]
public string AwsSdkVersion { get; set; }
[JsonPropertyName("clientId")]
public string ClientId { get; set; }
}
public class Request
{
[JsonPropertyName("userAttributes")]
public Dictionary<string, string> UserAttributes { get; set; }
[JsonPropertyName("validationData")]
public Dictionary<string, string> validationData { get; set; }
}
public class Response
{
}
Let me mention a tip for this kind of scenarios:
Write the handler as:
public dynamic ExampleTrigger(dynamic request, ILambdaContext context)
{
return request
}
Add the following environment variable for lambda.
LAMBDA_NET_SERIALIZER_DEBUG = true
Invoke the Auth flow and check the logs on CloudWatch. You can see the content of the incoming event object.
I am consuming a REST API - which returns JSON. I deserialize the JSON using NewtonSOFT JSON in C#.
The returned JSON contanins an "Answer" object that contain another "Answer" object - problem is that the 2 "Answer" objects has different properties / definitions.
How can that be handled in C# or in NewtonSoft?
Json structure
"answers": [
{
"tag": {
"id": 803,
"name": "Oplysninger om bestilling af tilstandsrapporten"
},
"option": false,
"answers": [
{
"label": "Vælg",
"value": "Ved hjælp af familie, venner eller bekendte mv",
"show_inline": false
}
],
"question": "Hvordan fandt du den bygningssagkyndige?",
"seller_question_id": 1
}
"answers" here is a property name, not a class name, so all you need to do is define your classes in a way that matches the pattern you've shown. Having two different properties named "answers" doesn't present any particular complication.
class Response
{
public IList<OuterAnswer> answers { get; set; }
}
class OuterAnswer
{
public Tag tag { get; set; }
public bool option { get; set; }
public IList<InnerAnswer> answers { get; set; }
public string question { get; set; }
public long seller_question_id { get; set; }
}
class InnerAnswer
{
public string label { get; set; }
public string value { get; set; }
public bool show_inline { get; set; }
}
My JSON looks like the following:
[
{
"id": "test.txt",
"fields": {
"_str.application": [ "Text File" ],
"_str.body": [ "asdsadasd" ],
"_str.mimetype": [ "text/plain" ]
}
}
]
How can I add new properties into fields from C# code?
I have already prepared for Serialization
public class Fields
{
[JsonProperty("_str.application")]
public IList<string> _str_application { get; set; }
[JsonProperty("_str.body")]
public IList<string> _str_body { get; set; }
[JsonProperty("_str.mimetype")]
public IList<string> _str_mimetype { get; set; }
}
public class Document
{
[JsonProperty("id")]
public string id { get; set; }
[JsonProperty("fields")]
public Fields fields { get; set; }
}
I need to add new JsonPropertys into Fields at runtime.
You can use Json.NET for deserialize as dynamic and adding fields in runtime, then serialize again:
string jsonText = "{'Bar':'something'}";
dynamic foo = JObject.Parse(jsonText);
foo.Dynamic="field";
jsonText = JsonConvert.SerializeObject(foo);
After hours of attempts and research, I am asking for your help.
I am calling a public API which returns the same structure except for the datas returned.
For examples, the REST calls which retrieve stations and districts return those two JSON answers :
Stations response :
"response" : {
"status": { "#attributes": {"code": "0", "message": "OK"} },
"data" : {
"station": [{
"number": "stationId",
"name": "stationName",
"address": "stationAddress",
"state": "1",
"latitude": "stationLat",
"longitude": "stationLong",
"slotsavailable": "10",
"bikesavailable": "20",
"pos": "0",
"district": "stationDistrict",
"lastupdate": "2016-03-28T11:47:08+02:00"
}, {...}, ...]}
}
Districts response :
"response" : {
"status": { "#attributes": {"code": "0", "message": "OK"} },
"data" : { "district": [{"id": "districtId", "name": "districtName"}, {...}, ...] }
}
I am using a .NET 4.5/C# solution with Newtonsoft.Json to execute the call.
I want to make the object, mapped to the client response, generic so the execution of the call will be made as follow :
var result = await client.Execute<Response<ApiResponseDistrict>>(request);
var result = await client.Execute<Response<ApiResponseStation>>(request);
My first attempt was to make a non generic call (create a full object by returned datas) which was a success.
My second attempt was to created a generic object so I made the following classes using the JsonProperty of the library Newtonsoft :
public class ApiResponse<T>
{
[JsonProperty("response")]
public Response<T> Response { get; set; }
}
public class Response<T>
{
[JsonProperty("status")]
public Status Status { get; set; }
[JsonProperty("data")]
public Data<T> Data { get; set; }
}
public class Data<T>
{
public T ResponseData { get; set; }
}
public class ApiResponseDistrict
{
[JsonProperty("district")]
public List<District> Districts { get; set; }
}
public class District
{
[JsonProperty("id")]
public int Id { get; set; }
[JsonProperty("name")]
public string Name { get; set; }
}
At this point, when I am executing the call the object Response is valorized and also its property Status with the value waited but the property Data is never valorized (null).
My third attempt was to continue on the second attempt but using the JsonObject of the Newtonsoft library which it's given (with the same result) :
[JsonObject("district")]
public class ApiResponseDistrict
{
public List<District> Districts { get; set; }
}
As I am new to Newtonsoft, I would like to know if it is possible to use generic classes, as I am trying to do, to mapped the object returned by the call or I have to create a complete object for each "data" returned ?
Thank you for your answer and explanations or clues for me to find the answer !
public class Response<T>
{
[JsonProperty("status")]
public Status Status { get; set; }
[JsonProperty("data")]
public Data<T> Data { get; set; }
}
public class Data<T>
{
public T ResponseData { get; set; }
}
This adds another layer between the data, so a response would look like this:
{
"Status": …,
"Data": {
"ResponseData": {
<The actual type T>
}
}
}
Instead, you want to remove that ResponseData level:
public class Response<T>
{
[JsonProperty("status")]
public Status Status { get; set; }
[JsonProperty("data")]
public T Data { get; set; }
}
So for example, for the JSON above, you would have a StationResponseData class:
public class StationResponseData
{
public List<Station> Stations
{ get; set; }
}
And then you would deserialize the JSON as Response<StationResponseData>. The Station class would then contain those properties for number, name, address, etc.
I have to deserialize the following json response (the Result list has variable length):
{
"ResultSet": {
"Query": "volkswagen",
"Result": [
{
"symbol": "VLKAY",
"name": "Volkswagen AG",
"exch": "PNK",
"type": "S",
"exchDisp": "OTC Markets",
"typeDisp": "Equity"
},
{
"symbol": "VOW3.DE",
"name": "Volkswagen AG",
"exch": "GER",
"type": "S",
"exchDisp": "XETRA",
"typeDisp": "Equity"
},
{
"symbol": "VOW.DE",
"name": "Volkswagen AG",
"exch": "GER",
"type": "S",
"exchDisp": "XETRA",
"typeDisp": "Equity"
}
]
}
}
What I got:
JavaScriptSerializer js = new JavaScriptSerializer();
string jsonString = "...String is here...";
SearchObj obj = js.Deserialize<SearchObj>(jsonString);
I understand that I usually have to create a fitting obj. e.g. SearchObj which will get filled but in this case I'm not entirely sure how this object is supposed to look like. I came up with:
class Data
{
public string symbol { get; set; }
public string name { get; set; }
public string exch { get; set; }
public string type { get; set; }
public string exchDisp { get; set; }
public string typeDisp { get; set; }
}
class Container
{
public string Query { get; set; }
public List<Data> Result { get; set; }
}
class SearchObj
{
public Container ResultSet { get; set; }
}
But guess what, it's not working, I only get ResultSet = null.
Try to change your class Container as
class Container
{
public string Query { get; set; }
public Data[] Result { get; set; }
}
I have not tested it, based on my observation
I always feel bad when I answer my own question but here it goes.
Basically my idea was correct, I only made one mistake which is that I don't need the
class SearchObj
{
public Container ResultSet { get; set; }
}
Using
Container obj = js.Deserialize<Container>(jsonString);
instead of
SearchObj obj = js.Deserialize<SearchObj>(jsonString);
made the trick. Both Data[] and List<Data> in Container work btw.
Edit:
From giammins comment it seems that it is working on some machines without that change but I guess that's a case for undefined behavior.
You can use http://www.json2charp.com to create your classes.