Error in serializing dictionary in Nancy - nancy

I have a route that returns a Dictionary like this:
public class HomeModule : NancyModule
{
public HomeModule()
{
Get["/"] = _ => new Dictionary<long, long> {{1, 2}, {3, 4}};
}
}
When I call it I got a response with status 200 but with response body like so:
Unexpected 'E'
What is wrong?
Nancy version 1.4.3.

JSON keys have to be string, so the dictionary should be in this format:
public class HomeModule : NancyModule
{
public HomeModule()
{
Get["/"] = _ => new Dictionary<string, long> {{"1", 2}, {"3", 4}};
// ^
}
}
And the result will be:
{
"1": 2,
"3": 4
}

There is an extension for IResponseFormatter you could use in the module that would solve this issue for you.
this.Response.AsJson(new Dictionary<int,int>{{2,4}});

Related

Why moving an array definition into another class changes its item type to a complex object?

I have an array in a NotationConstant class:
export class NotationConstant {
public static readonly TIME_SIGNATURES: Array<number> = [2, 4];
}
Then I use it in another SettingsDialogComponent class:
private instantiateLists(): void {
NotationConstant.TIME_SIGNATURES.forEach((timeSignature: number) => {
console.log(timeSignature);
this.timeSignatures.push({ 'id': timeSignature, 'name': String(timeSignature) });
});
}
The console log statement show:
{id: 2, name: "2"}
{id: 4, name: "4"}
Where do these id property and name property come from ?
Another stranger thing.
I add the array definition in the SettingsDialogComponent class:
public static readonly TIME_SIGNATURES: Array<number> = [2, 4];
private instantiateLists(): void {
SettingsDialogComponent.TIME_SIGNATURES.forEach((timeSignature: number) => {
console.log(timeSignature);
this.timeSignatures.push({ 'id': timeSignature, 'name': String(timeSignature) });
});
}
Now the console log statement shows:
2
4
Why moving the array definition into another class changes its traversing ?
UPDATE: The issue is gone. The above source code is exactly the same. High chaparral.

Data Class Either Object or Array

I have a Kotlin data class that has an arg that can either be an Object or Array. Is there a way to de-serialize a string into this class and not care if not an Array but somehow get it into an array of one?
data class Game(var name:List<NameItem>)
data class NameItem(var title: String, var id: Int)
data can come back as both ways a single object or an array of objects( I have no control over the data as it is 3rd party data.
jsonString = "{"game":{"name":{"title":"GameName","id":22}}}"
jsonString = "{"game":{"name":[{"title":"GameName","id":22},{"title":"GameName2","id":23}]}}"
game: Game? = Gson().fromJson(jsonString Game::class.java)
You have to write a custom JsonDeserializer. Both or your class should have the same parent class. Then, write a custom JsonDeserializer for this specific type.
For example:
sealed class GameParent() {
data class Game(val name: String): GameParent()
data class GameList(val games: List<Game>): GameParent()
}
class GameDeserializer : JsonDeserializer<GameParent> {
override fun deserialize(json: JsonElement?, typeOfT: Type?, context: JsonDeserializationContext?): GameParent {
with(json) {
if(isJsonObject) {
// parse as Game
}
if(isJsonArray) {
// parse as GameList
}
}
}
}
Then, in your GsonBuilder you have to register this custom JsonDeserializer:
gsonBuilder.registerTypeAdapter(GameParent::class.java, GameDeserializer());
Now, whenever your Gson expect GameParent will use registered deserializer.
my suggestions for solving your task
my solution if name is object, replace it with arrays
data class Game(var name:List<NameItem> )
data class NameItem(var title: String, var id: Int)
fun main(args: Array<String>) {
var json = "{\"game\":{\"name\":[{\"title\":\"game 1\",\"id\":1},{\"title\":\"game 2\",\"id\":2}]}}"
println(useJsonParser(json)) //Game(name=[NameItem(title=game 1, id=1), NameItem(title=game 2, id=2)])
json = "{\"game\":{\"name\":[{\"title\":\"game 1\",\"id\":1}]}}"
println(useJsonParser(json)) //Game(name=[NameItem(title=game 1, id=1), NameItem(title=game 2, id=2)])
json = "{\"game\":{\"name\":{\"title\":\"game 1\",\"id\":1}}}" // not array
println(useJsonParser(json)) //Game(name=[NameItem(title=game 1, id=1)])
}
version 1 -- created and registry adapter link #Cililing
fun useJsonParser(json: String): Game? {
val gson = GsonBuilder().registerTypeAdapter(Game::class.java, GameDeserializer()).create()
return gson.fromJson(json, Game::class.java)
}
class GameDeserializer : JsonDeserializer<Game?> {
override fun deserialize(json: JsonElement?, typeOfT: Type?, context: JsonDeserializationContext?): Game? {
val gameJson = json!!.asJsonObject.get("game")
if (gameJson.isJsonObject) {
val jsonName = gameJson.asJsonObject["name"]
val list = if (jsonName.isJsonObject) {
arrayOf(Gson().fromJson(jsonName, NameItem::class.java))
} else {
val fromJson = Gson().fromJson(jsonName, Array<NameItem>::class.java)
fromJson
}.toList()
return Game(list)
}
return null
}
}
version 2 -- manipulating the response
fun useJsonParser(json:String):Game?{
val jsonObject = JsonParser().parse(json).asJsonObject.get("game")
if(jsonObject.asJsonObject["name"].isJsonObject){
val jsonName = jsonObject.asJsonObject["name"].asJsonObject
val array = JsonArray()
array.add(jsonName)
jsonObject.asJsonObject.add("name", array) // rewrite origin JSON
}
return Gson().fromJson(jsonObject, Game::class.java)
}
vesrion 3 -- add adapter TypeToken>()
fun useJsonParser(json: String): Game? {
val type = object : TypeToken<MutableList<NameItem>>() {}.type
val gson = GsonBuilder().registerTypeAdapter(type, NameItemDeserializer()).create()
return gson.fromJson(JsonParser().parse(json).asJsonObject.get("game"), Game::class.java)
}
class NameItemDeserializer : JsonDeserializer<List<NameItem>?> {
override fun deserialize(json: JsonElement, type: Type, context: JsonDeserializationContext?): List<NameItem>? {
with(json){
return if(isJsonObject){
arrayListOf(Gson().fromJson(this,NameItem::class.java))
}else{
Gson().fromJson(this,Array<NameItem>::class.java).toList()
}
}
}
}

How to accessing properties of object Struct type, and then use it separately? (Swift)

I need to assign a property of an object of type Struct.
Here my Struct:
public struct Destinos: Data {
public var idDestino : Int?
public var desDestino : String? }
I have a 2 class when accessing he property like this:
class Api {
var listado = [Destinos]()
func GetDestinos(){
listado.append(Destinos(idDestino: 1, desDestino: "AsunciĆ³n"))
listado.append(Destinos(idDestino: 2, desDestino: "Miami"))
listado.append(Destinos(idDestino: 3, desDestino: "Atenas"))
listado.append(Destinos(idDestino: 4, desDestino: "Londres"))
listado.append(Destinos(idDestino: 5, desDestino: "Madrid"))
}
}
class DestinoPresenter {
var ListaDeDestinos = [String]()
fileprivate var DestinoLista: Api!
func searchDestinos(_ substring: String) {
DestinoLista = Api()
DestinoLista.GetDestinos()
//string member variable of each listados object
for object in DestinoLista.listado {
if (object.desDestino?.lowercased().contains(substring.lowercased()))! {
ListaDeDestinos.append(object.desDestino!)
}
}
mview.mostarResultados(ArrayResultados: DestinoLista.listado)
}
}
Method of another class:
func mostarResultados( ArrayResultados: [Destinos]) {
autoCompleteDestino = ArrayResultados
tableView.reloadData()
}
Now for the method mostarResultado is where I just need to print desDestino property... I try different ways without success until now... help me please.
Have you tried like this?
func mostarResultados( ArrayResultados: [Destinos]) {
autoCompleteDestino = ArrayResultados
for item in autoCompleteDestino{
print(item.desDestino)
}
tableView.reloadData()
}

Json Parsing in Angular2

I have a array of jsons that I want to parse to my class Tournament.
The class Tournament looks like this:
export class Tournament { constructor (public id: number,
public name: string,
public date: string,
public pointsWin: string,
public pointsDraw: string,
public groupSize: string,
public groupPhase: string,
public system: string,
public teams: Team[]
){ }
}
The class Team looks like this:
export class Team { constructor (public id: number,
public name: string,
public rank: number,
public occupied: boolean,
public group: string
){ }
}
And the JSON that i receive looks like this:
[{"id":1,
"name":"Schulcup1",
"date":
{"year":2017,"month":"MARCH","era":"CE","dayOfYear":83,"dayOfWeek":"FRIDAY","leapYear":false,"dayOfMonth":24,"monthValue":3,"chronology":{"calendarType":"iso8601","id":"ISO"}},
"pointsWin":0,
"pointsDraw":0,
"groupSize":0,
"groupPhase":null,
"system":null,
"teams":[
{"id":1,"name":"Team1","rank":8,"occupied":false,"group":"A"},
{"id":2,"name":"Team2","rank":1,"occupied":false,"group":"A"},
{"id":3,"name":"Team3","rank":4,"occupied":false,"group":"A"},
{"id":4,"name":"Team4","rank":16,"occupied":false,"group":"A"},
{"id":5,"name":"Team5","rank":2,"occupied":false,"group":"B"},
{"id":6,"name":"Team6","rank":16,"occupied":false,"group":"B"},
{"id":7,"name":"Team7","rank":8,"occupied":false,"group":"B"},
{"id":8,"name":"Team8","rank":4,"occupied":false,"group":"B"}],
"active":true},
{"id":2,
"name":"Schulcup2",
"date":
{"year":2017,"month":"MARCH","era":"CE","dayOfYear":82,"dayOfWeek":"THURSDAY","leapYear":false,"dayOfMonth":23,"monthValue":3,"chronology":{"calendarType":"iso8601","id":"ISO"}},
"pointsWin":0,
"pointsDraw":0,
"groupSize":0,
"groupPhase":null,
"system":null,
"teams":[
{"id":48,"name":"Team1","rank":16,"occupied":false,"group":"A"},
{"id":49,"name":"Team2","rank":2,"occupied":false,"group":"A"},
{"id":50,"name":"Team3","rank":4,"occupied":false,"group":"A"},
{"id":51,"name":"Team4","rank":1,"occupied":false,"group":"A"},
{"id":52,"name":"Team5","rank":16,"occupied":false,"group":"B"},
{"id":53,"name":"Team6","rank":8,"occupied":false,"group":"B"},
{"id":54,"name":"Team7","rank":16,"occupied":false,"group":"B"},
{"id":55,"name":"Team8","rank":16,"occupied":false,"group":"B"}],
"active":true}]
If I try to parse the JSON with JSON.parse() I get an error that there is an unexpected token in JSON at position 0 most likely because of the [ since it is an array of JSON but how can I iterate through it?
And also how can I iterate through the teams in the JSON to create an array of teams?
It is already parsed. Just use it as an object!
No need to use classes here, simply cast your JSON to interfaces, if you really do not need classes. Casting to interfaces is easy and painless ;) And no need of using JSON.parse here.
So use interfaces if you can, here is Tournament:
export interface Tournament {
public id: number,
public name: string,
public date: string,
public pointsWin: string,
public pointsDraw: string,
public groupSize: string,
public groupPhase: string,
public system: string,
public teams: Team[]
}
Service:
getTournaments(): Observable<Tournament[]> {
return this.http.get('src/data.json')
.map(res => res.json() as Tournament[])
}
TS:
tournaments: Tournament[] = [];
getTournaments() {
this.service.getTournaments()
.subscribe(data => {
this.tournaments = data;
})
}
DEMO

How to include structured data as a parameter of a HTTP GET request?

I would like to include stuctured data as a parameter to my HTTP GET call and think I have it set up correctly, but my API is not receiving the data as I expected. How do I set up both sides to communicate the structured data?
My angular application is asking a complicated question to the REST API written in Web API 2.
The controller method is defined as:
[RoutePrefix("v1/questions")]
public class VersionsController : ApiController
{
[Route("askComplicated")]
[HttpGet]
[ResponseType(typeof(ComplicatedResponseDto))]
public IHttpActionResult AskComplicatedQuestion(ComplicatedRequestDto complicatedRequest)
{
var responseElements = new List<ComplicatedResponseElementDto>();
foreach (var requestElement in complicatedRequest.Elements)
{
responseElements.Add(new ComplicatedResponseElementDto()
{
Id = requestElement.Id,
answer = "it is unknowable!!!"
});
}
return Ok(new ComplicatedResponseDto() { Elements = responseElements.ToArray()});
}
The DTOs:
public class ComplicatedRequestDto
{
public ComplicatedRequestElementDto[] Elements { get; set; }
}
public class ComplicatedRequestElementDto
{
public int Id { get; set; }
public string Question { get; set; }
}
public class ComplicatedResponseDto
{
public ComplicatedResponseElementDto[] Elements { get; set; }
}
public class ComplicatedResponseElementDto
{
public int Id { get; set; }
public string Answer { get; set; }
}
I broke it down this way because I like a simple request and a simple response. I'm adopting the patterns that worked best for my past WCF work (and understand that might be my problem here).
From the angular side, here is my code:
var request = $http({
method: "get",
url: "http://localhost:65520/v1/questions/askComplicated",
data: {
complicatedRequest : {
elements: [
{ id: 2, question: 'what is the meaning of life?' },
{ id: 3, question: 'why am I here?' },
{ id: 4, question: 'what stock should I pick?' }
]
}
}
});
return request.then(handleSuccess, handleError);
When I call the REST API from my angular application, the WEB API 2 application receives it, but the ComplicatedRequestDto is null. How do I properly send that data so it will go through?
Update your API from Get to Post, because when we want to pass complex object it contains more data and we have restrictions to send maximum characters in URL.
Do below modifications:
[RoutePrefix("v1/questions")]
public class VersionsController : ApiController
{
[Route("askComplicated")]
[HttpPost]
[ResponseType(typeof(ComplicatedResponseDto))]
public IHttpActionResult AskComplicatedQuestion([FromBody]ComplicatedRequestDto complicatedRequest)
{
//write ur code here...
}
}
Update your js code as below:
var request = $http({
method: "post",
url: "http://localhost:65520/v1/questions/askComplicated",
data: {
complicatedRequest : {
elements: [
{ id: 2, question: 'what is the meaning of life?' },
{ id: 3, question: 'why am I here?' },
{ id: 4, question: 'what stock should I pick?' }
]
},
}
});
return request.then(handleSuccess, handleError);
You should add [FromUri] anotation before the method parameter to inform WebAPI that you want to load this parameter from the application Uri, and this is where your data goes when you use GET http action with data parameter.
So your code should look like this
[RoutePrefix("v1/questions")]
public class VersionsController : ApiController
{
[Route("askComplicated")]
[HttpGet]
[ResponseType(typeof(ComplicatedResponseDto))]
public IHttpActionResult AskComplicatedQuestion([FromUri]ComplicatedRequestDto complicatedRequest)
{
var responseElements = new List<ComplicatedResponseElementDto>();
foreach (var requestElement in complicatedRequest.Elements)
{
responseElements.Add(new ComplicatedResponseElementDto()
{
Id = requestElement.Id,
answer = "it is unknowable!!!"
});
}
return Ok(new ComplicatedResponseDto() { Elements = responseElements.ToArray()});
}
You also have to correct the payload to match stucture of your classes.
The corect value should look like this:
{
"Elements": [
{
"Id": 1,
"Question": "sample string 2"
},
{
"Id": 1,
"Question": "sample string 2"
}
]
}
And finally to provide the JavaScript code example it will be like (I only have jQuery, but payload will be the same for Angular):
$.ajax({url:"/v1/questions/askComplicated",data: {
"Elements": [
{
"Id": 2,
"Question": "what is the meaning of life?"
},
{
"Id": 3,
"Question": "why am I here?"
}
]
}})

Resources