In my Lambda I am throwing custom error but from the vtl I am unable to get that when testing in Postman. In the postman I am keep getting message "A custom error was thrown from a mapping template." but I am expecting to get message and object from the custom class like source and errors
Here is my lambda function and custom error file
Custom Error file
export class ApiError extends Error {
source: string
args: string | undefined
errors: [{[key: string]: string | {[key: string]: string}}] | null | string
constructor(source: string, methodArgs: string, errors: [{[key: string]: string | {[key: string]: string}}] | null | string ) {
super();
this.source = source
this.args = methodArgs
this.errors = errors
}
}
export const completeProcess: Handler = async (event: any): Promise<CustomResponse> => {
const { customerId } = event.arguments.request as CustomRequest
if (customerId === null) {
throw new ApiError("completeProcess", JSON.stringify(event.arguments.request), "customerId missing")
}
}
Vtl file
request.vtl
{
"version": "2018-05-29",
"operation": "Invoke",
"payload": {
"field": "getError",
"arguments": $utils.toJson($context.arguments)
}
}
response.vtl
#if($context.error)
$utils.error($context.result.source, $context.result.errors)
#else
$utils.toJson($context.result)
#end
When running with above files I am keep getting response as
{
"data": {
"completeProcess": null
},
"errors": [
{
"path": [
"completeProcess"
],
"data": null,
"errorType": null,
"errorInfo": null,
"locations": [
{
"line": 2,
"column": 2,
"sourceName": null
}
],
"message": "A custom error was thrown from a mapping template."
}
]
}
Related
I have configured the JsonSerializerOptions's PropertyNamingPolicy as null, OData all results gets as expected, but BadRequestObjectResult is still using camelcase policy.
builder.Services.AddControllers()
.AddJsonOptions(options => {
options.JsonSerializerOptions.PropertyNamingPolicy = null; // to don't change property names lowercase
options.JsonSerializerOptions.DictionaryKeyPolicy = null;
})
protected ActionResult ValidationFailed()
{
var err = new ODataError
{
Message = "Validation error",
Details = ModelState.ToDictionary(
kvp => kvp.Key, //.ToCamelCase(),
kvp => kvp.Value.Errors.Select(e => e.ErrorMessage).ToArray()
).Select(e => new ODataErrorDetail() {
ErrorCode = e.Key,
Message = string.Join("\n", e.Value.ToArray())
}).ToList()
};
return new BadRequestObjectResult(err);
}
{
"error": {
"code": "",
"message": "Validation error",
"details": [
{
"code": "person.corpid",
"message": "Corpid field must be value"
}
]
}
}
I want to get all results without changed like following.
{
"Error": {
"Code": "",
"Message": "Validation error",
"Details": [
{
"Code": "Person.Corpid",
"Message": "Corpid field must be value"
}
]
}
}
as a young typescript padawan
i am trying to parse mock data from a json witch involves initializing a Map<string, MenuPageData>
and i get an error (attached below)
i would like to be able to supply the correct data format in the json or map it properly from the existing data.
here is the error:
here is the code:
export interface MenuItem {
data: {
id: string;
name: string;
currency?: string;
imageUrl?: string;
description?: string;
price?: number;
};
}
export interface MenuPageData {
pageName: string;
menuItems: MenuItem[];
}
export interface MenuPageDataCollection {
menuPages: Map<string, MenuPageData>;
}
the error is comming from "(pagesDataMock.menuPages)"
const dataCollection: MenuPageDataCollection = { menuPages: new Map<string, MenuPageData>(pagesDataMock.menuPages) };
export const menuPagesCollection: () => MenuPageDataCollection = (): MenuPageDataCollection => {
return dataCollection;
};
and here is the json source:
{
"menuPages": [
"mealPage1",
{
"pageName": "menuPage1",
"menuItems": [
{
"data": {
"id": "null0",
"name": "meal",
"currency": "EUR",
"imageUrl": "../images/greenHand.jpg",
"description": "tasty",
"price": 12
}
},
{
"data": {
"id": "null0",
"name": "meal",
"currency": "EUR",
"imageUrl": "../images/greenHand.jpg",
"description": "tasty",
"price": 12
}
}
]
},
"mealPage2",
{
"pageName": "menuPage1",
"menuItems": [
{
"data": {
"id": "null0",
"name": "meal",
"currency": "EUR",
"imageUrl": "../images/greenHand.jpg",
"description": "tasty",
"price": 12
}
},
{
"data": {
"id": "null0",
"name": "meal",
"currency": "EUR",
"imageUrl": "../images/greenHand.jpg",
"description": "tasty",
"price": 12
}
}
]
}
]
}
i would appreciate and feedback, i tried several different ways of doing it but now 3-4 days passed by and i am running on empty of understanding
Map is a rather strong constraint that is not representable in JSON as is. First you'll have to validate the input is satisfying the requirements for your Map<string, MenuPageData>. Then to make it understandable by TS wrap in into type guard or type assert function. And finally convert it into the actual Map object yourself.
Simplified example:
interface IFace {
prop: string
}
interface Res {
title: string
ifaceMap: Map<string, IFace>
}
interface ResJSON {
title: string
ifaceMap: { [K in string]: IFace }
}
function assertResponse(json: unknown): asserts json is ResJSON {
...
}
function convert2Res(res: ResJSON): Res {
const { title, ifaceMap } = res
const map = new Map()
for(let key in ifaceMap) map.set(key, ifaceMap[key])
return { title, ifaceMap: map }
}
assertResponse(goodResponse)
const mapRes = convert2Res(goodResponse)
TS playground
In case you have full control of the source json and absolutely sure it may never be misshaped you may completely skip the assert part and feed the response (forcibly asserted to ResJSON type) right into convert2Res.
So I am new to flutter development and this is the first thing I stumbled over.
I want to read a json file and "convert" it to dart classes.
This is my JSON file:
[
{
"name": "Deutsch",
"topics": [
{
"name": "Rechtschreibung",
"contents": []
},
{
"name": "Grammatik",
"contents": []
},
{
"name": "Textanalyse",
"contents": []
}
]
},
{
"name": "Mathematik",
"topics": [
{
"name": "Vektorrechnung",
"contents": []
},
{
"name": "Geometrie",
"contents": []
},
{
"name": "Polynomdivision",
"contents": []
}
]
}
]
This is my subject model:
import './topic.dart';
class Subject {
String _name;
List<Topic> _topics;
Subject(this._name, this._topics);
factory Subject.fromJSON(Map<String, dynamic> json) {
if (json != null) {
return Subject(json['name'], json['topics']);
} else {
return null;
}
}
get name => this._name;
get topics => this._topics;
}
and this the topic model:
import './content.dart';
class Topic {
String _name;
List<Content> _contents;
Topic(this._name, this._contents);
factory Topic.fromJSON(Map<String, dynamic> json) {
if (json != null) {
return Topic(json['name'], json['contents']);
} else {
return null;
}
}
get name => this._name;
get contents => this._contents;
}
The error message raises in the subject model at json['topics']:
_TypeError (type 'List<dynamic>' is not a subtype of type 'List<Topic>')
I would be really grateful if someone has a clue how I can get around this!
Thanks.
If you are sure that you will always have Topic in json['topics']
then you can cast it before adding it to subject:
return Subject(json['name'], json['topics'] as Topic);
When my endpoint's JSON response's "data" element returns results, I am successfully parsing said results out into a Map<String, MyCustomDataType>.
But when my endpoint's JSON response's "data" element returns empty e.g. "data": [],
my deserializing throws an error of "Invalid JSON at linenumber: Expected '{, kind: kotlinx.serialization.StructureKind$Map#6f12df1'"
In different endpoints where I use a List to deserialize the data element I could handle this empty data array result without an error by doing
#SerialName("data")
List<DataItem> = listOf(),
How do I handle this similarly using a map now? This is what I am currently unsuccessfully trying:
#Serializable
data class MyDataClass(
#SerialName("success")
var success: Boolean = false,
#SerialName("data")
var `data`: Map<String, MyCustomDataType> = emptyMap(),
#SerialName("statusCode")
var statusCode: Int = 0
) {
#Serializable
data class MyCustomDataType(
#SerialName("updated")
var updated: List<Updated> = listOf(),
#SerialName("deleted")
var deleted: List<Deleted> = listOf()
) {
#Serializable
data class Updated(
#SerialName("myid")
var uid: Int? = 0
)
#Serializable
data class Deleted(
#SerialName("myId")
var uid: Int? = 0
)
}
}
Sample JSON Response when it parses correctly:
"myDataClass": {
"success": true,
"data": {
"39": {
"updated": [
{
"myid": 1794
}
]
},
"75": {
"updated": [
{
"myid": 1794
}
]
}
},
"statusCode": 200
}
Sample JSON when it throws an error:
{
"myDataClass":{
"success":true,
"data":[],
"statusCode":200
}
}
I've made one of my API endpoints and inner logic asynchronous and when previously I've used Response.AsJson(Foo.bar()) , it would return the json representation normally, but now I see this appended to it:
{
"result": [
{
"id": "59d680cc734d1d08b4e6c89c",
"properties": {
"name": "value"
}
}
],
"id": 3,
"exception": null,
"status": 5,
"isCanceled": false,
"isCompleted": true,
"isCompletedSuccessfully": true,
"creationOptions": 0,
"asyncState": null,
"isFaulted": false
}
But I want it to be like this:
"id": "59d680cc734d1d08b4e6c89c",
"properties": {
"name": "value"
}
As I understand, it's because I've wrapped my object in a Task , but I can't figure out, how with Nancy framework, which I use the Response.AsJson, to make it so the properties are excluded. I can obviously omit the Response.AsJson of the returned object, but then response is no longer Json if requesting through web-browser for example.
For further example
NancyModule for routing API:
public ItemCatalogModule(IItemCatalog itemCatalog) : base("/itemCatalog")
{
Get("/fetch/{id}", async parameters =>
{
var id = (string) parameters.id;
var response = await Response.AsJson(itemCatalog.GetItem(id));
return response;
});
}
How the interface looks like of ItemCatalog:
public interface IItemCatalog
{
Task<Item> GetItem(string id);
}
You shoud do this :
public ItemCatalogModule(IItemCatalog itemCatalog) : base("/itemCatalog")
{
Get("/fetch/{id}", async parameters =>
{
var id = (string) parameters.id;
return Response.AsJson(await itemCatalog.GetItem(id));
});
}