Gurus,
I have a pesky problem with a simple AWS C# Lambda function. How to serialize fields with hyphen in their names? For example:
{ "detail-type" = "ABC", "event-id" = "123" }
If I use the [assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer))] it is not able to parse it into a field inside a class like this
public class Test
{
public string DetailType { get; set; }
public string EventId { get; set; }
}
I am not sure if either I can substitute the Deserializer with a different one or if I can add attributes to the Field Property in the class so that it can recognize an hyphenated input field and read it.
Any help is greatly appreciated!
I found out the solution! It seems Amazon.Lambda.Serialization.SystemTextJson (version 1.7 and beyond) makes use of the System.Text.Json namespace! So basically we can use the JsonPropertyName attribute to control the deserialization. I have shown an example below.
JSON
{ "detail-type" = "ABC", "event-id" = "abc123" }
C# Class
using System.Text.Json.Serialization;
public class Test
{
[JsonPropertyName("detail-type")]
public string DetailType { get; set; }
[JsonPropertyName("event-id")]
public string EventId { get; set; }
}
Lambda
public string FunctionHandler(Test input, ILambdaContext context)
{
return "Success!";
}
Related
At the beginning I want to say that 'm not a C# developer by any means, however at my work I've received a task where I have to write simple web service in .net.
The task is not very complicated however I've encountered the problem that JSON payload which is sent to our web service has "System" in property names:
"resource": {
"fields": {
"System.AreaPath": "someData",
"System.TeamProject": "someData",
"System.IterationPath": "someData"
}
}
I'm trying to get those values by using:
public class Resource
{
public Fields System.AreaPath { get; set; }
}
However I'm getting an error ("System" is a namespace but used like a type.)
Are there any best practices on how to perform such task ?
Thank you.
One easy option it to specify the JSON property in an attribute. If you're using Json.NET you can use [JsonProperty] for this. Complete example:
using System;
using System.IO;
using Newtonsoft.Json;
public class Fields
{
[JsonProperty("System.AreaPath")]
public string AreaPath { get; set; }
[JsonProperty("System.TeamProject")]
public string TeamProject { get; set; }
[JsonProperty("System.IterationPath")]
public string IterationPath { get; set; }
}
public class Resource
{
public Fields Fields { get; set; }
}
class Program
{
static void Main()
{
string json = File.ReadAllText("test.json");
var resource = JsonConvert.DeserializeObject<Resource>(json);
Console.WriteLine(resource.Fields.TeamProject);
}
}
JSON (removed the "resource" part to make it a complete JSON document; I assume you know how to handle this if necessary):
{
"fields": {
"System.AreaPath": "someData",
"System.TeamProject": "team project",
"System.IterationPath": "someData"
}
}
Output: team project
I've got some difficulties with this json script:
{
"insured_agent_flag": "a",
"id": "1",
"agent": {
"fullName": "John Travolta",
"mobileNumberPdf": "+987654321",
"mobileNumber": "",
"identityCard": {
"identityCardExpirationDate": null
},
"secondIdentityCard": {
"identityCardExpirationDate": null
},
"notes": {},
"sign": "ADVANCED"
},
"basicData": {
"personType": "PERSON",
"agreeWithCompleteAnalysis": false,
"investmentInterest": false
},
"nonOfferedProducts": [
"PROD_A",
"PROD_B",
"PROD_C"
]
}
I would like to get some parameters from this script and put it into sql server table.
In order to do that, I used and transformed a C# script shared by https://mycontraption.com:
using System;
using System.Data;
using System.Collections.Generic;
using System.Linq;
using Microsoft.SqlServer.Dts.Pipeline.Wrapper;
using Microsoft.SqlServer.Dts.Runtime.Wrapper;
using System.Web.Script.Serialization;
using Microsoft.SqlServer.Dts.Pipeline;
namespace SC_c7e2d8c3918d46a5a07a1b438ddc7642
{
public class BasicData
{
public string agreeWithCompleteAnalysis { get; set; }
public string inOtherSystem { get; set; }
public string investmentInterest { get; set; }
}
public class ParentObject
{
public BasicData BasicData { get; set; }
public int id { get; set; }
public string insured_agent_flag { get; set; }
public IEnumerable<string> NonOfferedProducts { get; set; }
}
[Microsoft.SqlServer.Dts.Pipeline.SSISScriptComponentEntryPointAttribute]
public class ScriptMain : UserComponent
{
public override void Input0_ProcessInputRow(Input0Buffer Row)
{
JavaScriptSerializer js = new JavaScriptSerializer();
// Give the input column a variable to make it easier to reference.
BlobColumn combinedColumn = Row.parameterscon;
// Convert from blob to string
string reviewConverted = System.Text.Encoding.ASCII.GetString(combinedColumn.GetBlobData(0, Convert.ToInt32(combinedColumn.Length)));
// Deserialize the string
ParentObject obj = js.Deserialize<ParentObject>(reviewConverted);
var rows = obj.NonOfferedProducts.ToList();
Row.agreeWithCompleteAnalysis = obj.BasicData.agreeWithCompleteAnalysis;
Row.inOtherSystem = obj.BasicData.inOtherSystem;
Row.investmentInterest = obj.BasicData.investmentInterest;
Row.projectionid = obj.id;
Row.insuredagentflag = obj.insured_agent_flag;
//Row.nonOfferedProducts =
}
}
}
For 'standard' objects it works fine, but there is a problem with array "nonOfferedProducts". After compiling I get an error:
„object reference not set to an instance of an object”.
Here are my questions:
1. How should I handle 'nonOfferedProducts' array in C# script?
2. Why do I get foregoing error?
3. Unfortunately there exists a possibility, that json scripts would have some errors, like missing braces. How should I handle that?
Thank you!
Thanks a lot for your answers. According to your comments I'll try to give you more explanations:
1. The json script I have added in this post - it's only small part of whole script. In complete script there is a lot of different parameters. What is more, my C# code should scan about 40.000 json scripts (stored in sql server table in one column). These scripts has got similiar structure - but not the same.
So I thought about C# resolution, that will be searching for the parameters that I need. For json scripts without these parameters the c# code will put nulls to the right output columns.
Here are my output columns:
-agreeWithCompleteAnalysis
-inOtherSystem
-investmentInterest
-projectionId
-insuredAgentFflag
-nonOfferedProducts
I understood, that structure of my classes were wrong - I'll improve that.
But I've got one doubt - is it possible to prepare c# code structure, that will handle only these parameters I need?
And finally, I would like to put the results into my database.
For example if nonOfferedProducts property will have 3 values (not always!), I'd like to send to my database table 3 records (3 different values for nonOfferedProducts column and 3 the same values for the rest columns -agreeWithCompleteAnalysis, inOtherSystem etc).
I hope that will be clear now.
Thanks a lot for your help!
J
Use https://quicktype.io and paste json, it will generate c# model and serializer code.
As I said in my comment, your c# model doesn't match the JSON object.
If the model was made up of various nested objects to better reflect the actual JSON then you'll have more luck:
public class IdentityCard
{
public DateTime? IdentityCardExpirationDate { get; set; }
}
public class Notes
{
//No idea what should be in here...
}
public class BasicData
{
public string PersonType { get; set; }
public bool AgreeWithCompleteAnalysis { get; set; }
public bool InvestmentInterest { get; set; }
}
public class Agent
{
public string FullName { get; set; }
public string MobileNumberPdf { get; set; }
public string MobileNumber { get; set; }
public IdentityCard IdentityCard { get; set; }
public IdentityCard SecondIdentityCard { get; set; }
public Notes Notes { get; set; }
public string Sign { get; set; }
}
//Note: THIS is the actual class that matches the JSON sample given.
public class ParentObject
{
public string insured_agent_flag { get; set; }
public int Id { get; set; }
public Agent Agent { get; set; }
public BasicData BasicData { get; set; }
public IEnumerable<string> NonOfferedProducts { get; set; }
}
Once the model is correct, then Deserialization works fine for me with the given example (I did this in a unit test, but assuming your string matches your example this should be fine)
//get json
string json = #"
{
""insured_agent_flag"": ""a"",
""id"": ""1"",
""agent"": {
""fullName"": ""John Travolta"",
""mobileNumberPdf"": ""+987654321"",
""mobileNumber"": """",
""identityCard"": {
""identityCardExpirationDate"": null
},
""secondIdentityCard"": {
""identityCardExpirationDate"": null
},
""notes"": {},
""sign"": ""ADVANCED""
},
""basicData"": {
""personType"": ""PERSON"",
""agreeWithCompleteAnalysis"": false,
""investmentInterest"": false
},
""nonOfferedProducts"": [
""PROD_A"",
""PROD_B"",
""PROD_C""
]
}";
var js = new JavaScriptSerializer();
ParentObject obj = js.Deserialize<ParentObject>(json);
//do things...
var rows = obj.NonOfferedProducts.ToList();
Assert.AreEqual(3, rows.Count);
Assert.AreEqual("PROD_A", rows.First());
The asserts pass - This code happily gets the list of strings in the NonOfferedProducts property with the given example.
Obviously if you cannot rely on the consistency of the JSON (either structure or how well-formed it is) then you'll have problems, but that's a different issue.
To answer your question no 2) you are getting the object reference error because the BasicDataClass.nonOfferedProducts is null and you are trying iterate over it , this may be a reason that you are sending the wrong json which JavaScriptSerializer is not able to deserilize.
your 3rd question you can always validate your json with json validators which are there online like https://jsonformatter.org/
I use ASP.NET Core WebAPI and i have method call that should return the following data:
{ "10v_module": 1, "core_module": 2 }
Since it is not possible to have a C# property that starts with a digit, how I will be able to do this?
Thanks!
it would be something like
class Program
{
public static void Main()
{
string s = "{ \"10v_module\": 1, \"core_module\": 2 }";
jsonData obj = JsonConvert.DeserializeObject<jsonData>(s);
}
}
public class jsonData
{
[JsonProperty("10v_module")]
public int v_module { get; set; }
[JsonProperty("core_module")]
public int core_module { get; set; }
}
With JSON.NET all you need is adding JsonProperty attribute and specify its custom name that appears in resulting JSON
You can use the JsonPropertyAttribute to give the property of your C# class a Json property name that starts with a digit.
[JsonProperty("10v_module")]
public string Tenv_module {get;set;}
I'm currently using a beta API (http://developer.riotgames.com/api/methods) which returns JSON for all the exposed methods.
I've been able to use JSON.NET to deserialize all of these return values so far. However, today I consumed one of their function which returns a JSON that is valid but is in my opinion not correct.
You're probably wondering, why don't you ask it on the beta forum? I have but I haven't received an answer so far and in general this intrigues me.
A snippet of the JSON return:
"1001": {
"name": "Boots of Speed",
"plaintext": "Slightly increases Movement Speed",
"group": "BootsNormal",
"description": "<...
}
The problem I have with this structure is that the ID is used as a "group" without an identifier. I would be able to use this decently if it had
"ItemID" : "1001"
But it doesn't have that. I don't mind manually parsing it but I'd first like to know whether or not this JSON is correct (not just valid).
Do you agree that this is not a clean way of creating a JSON block that contains a list of elements or am I missing something here? So far I haven't seen any comments on the beta forum of this API so I'm really wondering why.
Edit "valid" vs "correct/usable":
I know it's a valid JSON statement. I'm questioning the fact whether this is usable with JSON.NET.
I have the following class definition (with two subclasses):
public class JSONItem
{
[JsonProperty("tags")]
public string[] Tags { get; set; }
[JsonProperty("plaintext")]
public string Plaintext { get; set; }
[JsonProperty("description")]
public string Description { get; set; }
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("into")]
public string[] Into { get; set; }
[JsonProperty("image")]
public JSONItemImage Image { get; set; }
[JsonProperty("colloq")]
public string Colloq { get; set; }
[JsonProperty("gold")]
public JSONItemGold Gold { get; set; }
}
When giving the above JSON block to to JSONConvert.DeserializeObject(json) it throws an error because "1001" is not mentioned in JSONItem.
How do you handle this so that you can use JSON.NET?
A class like this won't work because you have no names to give the properties:
public class JSONItemWrapper
{
[JsonProperty("")]
public string ID { get; set; }
[JsonProperty("")]
public JSONItem MyProperty { get; set; }
}
Edit: "consistent with other methods"
The other methods return blocks where every property is within {} and has an identifier. The most recently added function have this "primary key outside of {}" style.
It is a valid json and you can use a type like Dictionary<string, SomeObject> to deserialize your json.
string json = #"{
""1001"": {
""name"": ""Boots of Speed"",
""plaintext"": ""Slightly increases Movement Speed"",
""group"": ""BootsNormal"",
""description"": ""desc...""
}
}";
var dict = JsonConvert.DeserializeObject<Dictionary<string, MyObject>>(json);
and accesing an item later on by its key can be fast too.
public class MyObject
{
public string name { get; set; }
public string plaintext { get; set; }
public string group { get; set; }
public string description { get; set; }
}
It's annoying when APIs do things like this (using numbers as property names), but all is not lost. Simply deserialize the JSON using Json.NET and then access each of the items using the indexer operator on the parent object.
EDIT:
I almost never create DTOs when deserializing JSON. It's lots of unnecessary boilerplate in most cases. I prefer deserializing to a dynamic object, but that won't be as effective when dealing with property names that begin with digits.
Here is how I would deserialize your sample message:
using System;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace JsonExample
{
internal class Program
{
private static void Main()
{
const string json = #"
{
'1001': {
'name': 'Boots of Speed',
'plaintext': 'Slightly increases Movement Speed',
'group': 'BootsNormal',
'description': '<...'
}
}";
var jObject = JsonConvert.DeserializeObject<JObject>(json);
var plaintext = jObject["1001"]["plaintext"].Value<string>();
Console.WriteLine(plaintext);
}
}
}
When put into http://JSONLint.com,
{
"1001": {
"name": "Boots of Speed",
"plaintext": "Slightly increases Movement Speed",
"group": "BootsNormal",
"description": "<..."
}
}
Validates as JSON.
I have a JSON string like:
var json = "{\"Attributes\": {\"name\":\"S1\", \"quantity\":\"100\"}}";
I want to design a class for the same; how does one approach while creating a class for JSON string in C# ?
If you are using Visual Studio 2012, go in the menu to EDIT -> Paste Special -> Paste JSON As CLasses.
You valid JSON should probably look like this (you should remove the \ before copying it to the clipboard):
{"Attributes": {"name":"S1", "quantity":"100"}}
The generated classes:
public class Rootobject
{
public Attributes Attributes { get; set; }
}
public class Attributes
{
public string name { get; set; }
public string quantity { get; set; }
}
Sample usage (note that the \ is still here, in order to have valid code syntax):
var json = "{\"Attributes\": {\"name\":\"S1\", \"quantity\":\"100\"}}";
var json_serializer = new JavaScriptSerializer();
Rootobject dc = json_serializer.Deserialize<Rootobject>(json);
You're question's unclear, but I assume you mean parsing JSON in to C# objects? Using JSON.NET and something like this can do that:
public class Attributes
{
[JsonProperty("name")]
public String Name { get; set; }
[JsonProperty("quantity")]
public Int32 Quantity { get; set; }
}
public class MyObject
{
[JsonProperty("Attributes")]
public Attributes Attributes { get; set; }
}
var myObj = JsonConvert.DeserializeObject<MyObject>(json);
Or you can go more broadly and let JSON.NET do it for you:
var obj = JsonConvert.DeserializeObject<dynamic>(
"{ \"Attributes\": {\"name\":\"S1\", \"quantity\":\"100\"}}"
);
Console.WriteLine(obj.Attributes["name"]) // S1
Console.WriteLine(obj.Attributes["quantity"]) // 100
have a look at the namespace System.Runtime.Serialization, you can find useful classes for (de)serializing JSON there
also you can read this similar question (searching before posting does not really hurt):
How do I represent this complex json document as a C# object?