Case
This case are using Scala, Play Framework, Jerkson and Squeryl. I'm trying to convert the query resultset to JSON but the result presents just the 'persisted' field.
Question
Why the Json.generate() is not printing all entity fields?
Controller
package controllers.api
import play.api.mvc._
import play.Logger
import play.api.data.Form
import play.api.data.Forms.{mapping, text, optional}
import com.codahale.jerkson.Json
import org.squeryl.PrimitiveTypeMode._
import models.{ApplicationDatabase, Category}
object Categories extends Controller {
def findAll = Action {
val json = inTransaction {
val list = from(ApplicationDatabase.categories)(categories =>
select(categories)
orderBy(categories.title)
)
Logger.info(list.toString)
Json.generate(list)
}
Ok(json).as(JSON)
}
def findById(id: Long) = Action {
val category = inTransaction {
ApplicationDatabase.categories.lookup(id)
}
Ok(Json.generate(category)).as(JSON)
}
}
Category Entity
package models
import org.squeryl.PrimitiveTypeMode._
import org.squeryl.annotations.Column
class Category(var uid: String, var title: String) extends FlashcardsDbObject {
}
Base Entity
package models;
import java.sql.Timestamp
import org.squeryl._
import org.squeryl.annotations.{Column}
import org.squeryl.PrimitiveTypeMode._
class FlashcardsDbObject extends KeyedEntity[Long] {
val id: Long = 0
#Column("created_at")
var createdAt = new Timestamp(System.currentTimeMillis)
#Column("updated_at")
var updatedAt = new Timestamp(System.currentTimeMillis)
}
Problem
Result
{
persisted: true
},
{
persisted: true
},
Expected
{
id: 1,
uid: 'chemistry',
title: 'Chemistry'
persisted: true
},
{
id: 2,
uid: 'biology',
title: 'Biology'
persisted: true
},
Probably this is not the best solution but when I imported and declared JsonProperty into the field worked for me:
package models
import org.squeryl.KeyedEntity
import org.squeryl.annotations._
import org.squeryl.PrimitiveTypeMode._
import org.codehaus.jackson.annotate.JsonProperty
case class Category(val id: Int = 0,
#JsonProperty("uid")
val uid: String,
#JsonProperty("title")
val title: String) extends KeyedEntity[Int] {
}
Result
[
{
id: 3,
uid: "biology",
title: "Biology"
},
{
id: 1,
uid: "general-chemistry",
title: "General Chemistry"
},
{
id: 4,
uid: "organic-chemistry",
title: "Organic Chemistry"
},
{
id: 2,
uid: "physics",
title: "Physics"
}
]
Related
I would like to create an instance of the Customer class from Json object.
But using the plainToInstance function of class-transformer I don't have the proper class instance as a type save typescript object.
What I'm doing bad?
Import
import { plainToInstance } from 'class-transformer';
Customer JSON
const json = `{
"id": "1",
"name": "Jogn",
"surname": "Doe",
"email": "j.doe.test#gmail.com",
"phone": "123456789"
}
}
`;
Customer class definition
import { Field, ObjectType, Directive, ID } from '#nestjs/graphql';
import { Address } from './address';
#ObjectType()
#Directive('#key(fields: "id")')
export class Customer {
#Field(() => ID)
id: string;
#Field()
name: String;
#Field({nullable: true})
surname?: String;
#Field()
email: String;
#Field({nullable: true})
phone?: String;
#Field()
customerType: String;
#Field()
customerStatus: String;
#Field(() => [Address], { nullable: true })
addresses?: [Address]
}
Transformation from Json to Customer instance
let customer : Customer = plainToInstance(Customer, json) as Customer;
console.log('customer.email);
Console result
Customer email: undefined
So I couldn't get the email of the customer here
This is what I have when I log the entire customer variable
console.log(customer);
{
"id": "1",
"name": "Jogn",
"surname": "Doe",
"email": "j.doe.test#gmail.com",
"phone": "123456789"
}
Test with creating the Customer instance inline
var x = new Customer();
x.id = "123";
console.log(x)
So, now the object looks properly in the console
Customer { id: '123' }
You must pass a json object to plainToInstance - not a string.
i.e. your json variable should be
const json = {
id: '1',
name: 'Jogn',
surname: 'Doe',
email: 'j.doe.test#gmail.com',
phone: '123456789',
};
here's a working Stackblitz example
The second attribute of plainToInstance should be a plain object so you have to parse your json string into an object:
let customer = plainToInstance(Customer, JSON.parse(json))
I have a json like this :
[ {
"id": 1,
"libraryName": "lib1",
"bookName": "book1",
"bookPrice": 250.45,
"unitSold": 305
},
{
"id": 2,
"libraryName": "lib1",
"bookName": "book2",
"bookPrice": 450.45,
"unitSold": 150
},
{
"id": 3,
"libraryName": "lib1",
"bookName": "book3",
"bookPrice": 120.25,
"unitSold": 400
}]
I want to recuperate all the bookNames of this json in a list without creating the method getBookNames (because I want a standard way for any field of the json)
So, in the component.ts I used :
sales:any;
getSale () {
this.service.getSales().subscribe(data=> {this.sales = data,
console.log(this.sales.bookName)
})
}
It gives me undefined object in the console ! How can I solve this without creating a method getBookNames() ?
This is my class :
export interface Sale {
id: number
bookname : string
Libraryname: string
Bookprice : number
Unitsold : number
}
This is my service:
import { Injectable } from '#angular/core';
import { HttpClient } from '#angular/common/http';
import { Sale } from './Sale';
#Injectable({
providedIn: 'root'
})
export class MyserviceService {
constructor(private http: HttpClient) { }
getSales () {
return this.http.get<Sale>("http://localhost:8081/sales/all")
}
}
The data obtained from the API is an array. So you could use array map() function to obtain a list of all the properties from the elements. Try the following
sales: any;
unitsSold = [];
getSale () {
this.service.getSales().subscribe(data=> {
this.sales = data,
console.log(data.map(item => item.bookName)); // <-- output: ['book1', 'book2', 'book3'];
console.log(data.map(item => item.id)); // <-- output: [1, 2, 3];
this.unitsSold = data.map(item => item.unitSold); // <-- [305, 150, 400]
});
}
I don't see anything lost here to recuperate.
Hello I am using GSON to parse a route object, which contains the following JSON:
{
"mapOverlays": [
{
"id": 1,
"route": 73,
"url": "https://en.wikiarquitectura.com/wp-content/uploads//2017/01/White_House_distr_2C2BA.png",
"lat": 0.00,
"lng": 0.00,
"width": 2000,
"height": 1335,
"scale": 1,
"constraints": {
"w": [
0.00,
0.00
],
"x": [
0.00,
0.00
],
"y": [
0.00,
0.00
]
},
"flags": ""
}
]
}
The issue is when I try to access the JsonObject of constraints, I get an empty JSONObject.
Here is the Data model class of the Basemaps.
import com.google.gson.JsonObject
import com.travelstorysgps.travelstoryssdk.extensions.md5
import java.io.Serializable
class Basemap (
val id: Int,
val route: Int,
val url: String,
val lat: Double,
val lng: Double,
val width: Int,
val height: Int,
val scale: Double,
val constraints : JsonObject ,
val flags: String
) : Serializable {
val filename: String
get() = url.md5() + ".file"
}
And this is the output I get when I call Basemap.constraints : I/System.out: [BASEMAP]: {} It should contain JSONArrays named w,x, and y.
Is there something wrong with my Data model class?
EDIT: Here is the parent Route object:
package com.travelstorysgps.travelstoryssdk.data.model
import android.content.Context
import com.travelstorysgps.travelstoryssdk.data.Location
import java.io.Serializable
import java.util.*
import kotlin.math.floor
data class Route(
val route: RouteDefinition,
val tracks: List<Track>,
val geotags: List<Geotag>,
val images: List<Image>,
val music: List<Music>,
val assets: AssetList,
val orgs: List<Organization>,
val mapOverlays: List<Basemap>,
val ecoupons: List<Coupon>,
var distance: Int,
var routeKey: String = "",
var isDownloading: Boolean = false
) : Serializable {
val artists: List<Int>
get() = music.map { it.artist }.distinct()
}```
The Basemap object is wrapped in parent JSON object under mapOverlays array field. You need an additional class to deserialize in proper structure.
data class Parent(val mapOverlays: List<Basemap>)
fun someFn(json: String) {
val parent = Gson().fromJson(json, Parent::class.java)
println(parent.mapOverlays[0].constraints)
}
I have a class which has multiple interfaces inside of it to model a JSON data. For example:
interface A {
id: number;
}
interface B {
name: string;
surname?: string;
}
class MyClass implements A {
people: B[];
notes: string[];
function1(){...}
function2(){...}
}
And I have a JSON in the same structure:
{
id: 1,
people: [
{
name: "john"
},
{
name: "alice",
surname: "smith"
}
],
notes: [ "Very important top secret note" ]
}
Can I create an instance of MyClass from this JSON directly?
Your data structure is almost the same as your class, you'd have to add an id property to the class
class MyClass implements A {
id: number;
// ....
}
The problem is if you were trying to do something like this:
let data: MyClass = {
id: 1,
people: [
{
name: "john"
},
{
name: "alice",
surname: "smith"
}
],
notes: [ "Very important top secret note" ]
}
This won't work because your json does not have the methods (function1, function2).
One solution would be to really instantiate the MyClass and pass the json, or have a constructor method for that like
class MyClass {
static createFrom(jsonData: A & B): MyClass {
// create the objct and return
}
}
Or, you could create a variable of that type by combining an existing instance of the class and spreading the json.
Like so:
let json = {
id: 1,
people: [
{
name: "john"
},
{
name: "alice",
surname: "smith"
}
],
notes: ["Very important top secret note"]
}
const c = new MyClass();
let mClass: MyClass = {...json, function1: c.function1, function2: c.function2 };
mClass.function1();
Link to playground
Let be this JSON string:
[
{
"id": 1,
"text": "Jon Doe"
},
{
"id": 1,
"text": "Pablo Escobar"
}
]
Let be this class:
export class MyObject{
id: number;
text: string;
}
How can I cast this JSON string to list of MyObject?
If I do:
console.log(<MyObject[]>JSON.parse(json_string));
It returns a list of Object instead of a list of MyObject
You don't necessarily need a class here. You can just use an interface
export interface MyObject{
id: number;
text: string;
}
Then you can just write:
var myObjArray : MyObject[] = [
{
"id": 1,
"text": "Jon Doe"
},
{
"id": 1,
"text": "Pablo Escobar"
}
];
If you data comes from the server, you will probably have it in a variable of type any, and you can just assign it to an array of that type and it will work as expected.
var data: any = getFromServer();
var myObjectArray:MyObject[] = data;
In typescript you don't need a class implementing an interface. Any object literal that satisfies the interface contract will do.
If your data is still in string for you can just use JSON.parse(jsonString) to parse the string to JavaScript objects.
See playground here
You will need to create a constructor for your class, and call it for each item in the list you receive.
export class MyObject{
constructor(public id: number, public text: string) { }
}
let data = [
{
"id": 1,
"text": "Jon Doe"
},
{
"id": 1,
"text": "Pablo Escobar"
}
];
let objects = data.map(o => new MyObject(o.id, o.text));
You can check it out in the playground here.
There is a problem when MyObject has 50 or more properties...
Add a constructor in your MyObject class so that it extends your json object.
export class MyObject {
constructor( json: any )
{
$.extend(this, json);
}
id : number;
text : string;
methodOnMyObject() {...}
}
In your ajax callback, create the MyObject object from your json Object:
let newObject = new MyObject( json );
newObject.methodOnMyObject();
I detailed the solution in that post.
One more way to achieve this:
var data: any = getFromServer();
var myObjectArray = data as MyObject;
Or:
var data: any = getFromServer();
var myObjectArray = <MyObject>dataMyObject;