Ember-Data: embedded objects in JSON data is lost - json

I have a model called ticket-stats, defined as follows:
import Model from 'ember-data/model';
import attr from 'ember-data/attr';
export default Model.extend({
opened24Hours: attr('number'),
miRelated: attr('number'),
autoClosed24Hours: attr('number'),
inQueue: attr('number'),
activeGreater48: attr('number'),
behindNct: attr('number'),
manuallyClosed24Hours: attr('number'),
handoff: attr('number')
});
The data for this comes from a service which yields the following JSON:
{
"get_tickets": {
"behind_nct": {
"inequality": null,
"stat_name": "Behind NCT",
"value": 0,
"update_time": "2016-05-26 18:05:11",
"threshold": null
},
...
}
}
I have a custom serializer for this model:
import JSONSerializer from 'ember-data/serializers/json';
export default JSONSerializer.extend({
normalizeResponse(store, primaryModelClass, payload, id, requestType) {
console.log(payload);
var data = {};
data.id = 1;
data.opened24Hours = payload.get_tickets.tickets_opened_last_24_hours.value;
data.miRelated = payload.get_tickets.mi_related_tickets.value;
data.autoClosed24Hours = payload.get_tickets.tickets_closed_goliath_last_24_hour.value;
data.inQueue = payload.get_tickets.tickets_in_queue.value;
data.activeGreater48 = payload.get_tickets.active_greater_48.value;
data.behindNct = payload.get_tickets.behind_nct.value;
data.manuallyClosed24Hours = payload.get_tickets.tickets_closed_last_24_hours.value;
data.handoff = payload.get_tickets.handoff_tickets.value;
return this._super(store, primaryModelClass, data, id, requestType);
}
});
The values for the attributes of my model are all null. When i look at the payload on the console, I see that the innermost objects (i.e. behind_nct) don't contain the correct attributes:
behind_nct: Object
__proto__: Object
__defineGetter__ : __defineGetter__()
__defineSetter__ : __defineSetter__()
__lookupGetter__ : __lookupGetter__()
__lookupSetter__ : __lookupSetter__()
constructor : Object()
hasOwnProperty : hasOwnProperty()
isPrototypeOf : isPrototypeOf()
propertyIsEnumerable : propertyIsEnumerable()
toLocaleString : toLocaleString()
toString : toString()
valueOf : valueOf()
get __proto__ : get __proto__()
set __proto__ : set __proto__()
Is there something wrong with the JSON api or with my configuration of the Ember model? Or both?
When i go to the URL for the json, everything seems fine. I can see all the data.

You need to form a correct JSON API payload from your server's response:
let ticks= payload.get_tickets;
let data= {
ticket_stats: [{
opened24Hours: ticks.tickets_opened_last_24_hours.value,
// etc. etc.
}]
};
You need to identify the model type ticket_stats in the payload.

Related

How to iterate over JSON returned by HttpClient

I have a simple Angular HttpClient, which is correctly returning JSON. I am attempting to cast the results to enforce type safety (not sure if this is correct).
But how do I actually access the returned JSON to copy it into an array?
The httpClient get() request is (and seems to be working fine):
public sendGetRequest(): Observable<Symbols[]> {
return this.httpClient.get<Symbols[]>(this.REST_API_SERVER);
}
The Symbols interface is
export interface Symbols {
code: string
desc: string
}
I have a component which calls the data service and is getting a response. However the code below returns an error when attempting to map the JSON into a string array
ERROR TypeError: syms.map is not a function
listOfOption: Array<{ value: string; label: string }> = []
this.dataService.sendGetRequest().subscribe((syms: Symbols[]) => {
console.log('return value ' + JSON.stringify(syms))
// console output shows the returned JSON and it looks correct
//this does not work, how do I copy the results to a string array??
this.listOfOption = syms.map(results => {
return {
value: results.code,
label: results.code,
}
})
})
The JSON data structure is:
{
"results": [
{
"code": "code1",
"desc": "Long description of code 1"
},
{
"code": "code2",
"desc": "Long description of code 2"
},
{
"code": "code3",
"desc": "Long description of code 3"
},
{
"code": "code4",
"desc": "Long description of code 4"
}
]
}
This is driving me crazy
Model a new interface called responseData to support response type.
export interface responseData{
results: Symbols[]
}
export interface Symbols {
code: string
desc: string
}
Update the same in service
public sendGetRequest(): Observable<responseData> {
return this.httpClient.get<responseData>(this.REST_API_SERVER);
}
You can now retrieve the results using array.map()
listOfOption: Array<{ value: string; label: string }> = []
this.dataService.sendGetRequest().subscribe((syms: responseData) => {
console.log('return value ' + syms)
this.listOfOption = syms.results.map(result => {
return {
value: result.code,
label: result.code,
}
})
})
The response data has an object root, but you're trying to parse it as an array root. I think the simplest solution would be something like this:
public sendGetRequest(): Observable<Symbols[]> {
return this.httpClient.get<{results: Symbols[]}>(this.REST_API_SERVER)
.pipe(pluck('results'));
}
Which specifies that the response data is an object with a field named results which holds an array of Symbols.
Alternatively you could also extract the response type to a separate definition:
interface ApiResponse {
results: Symbols[]
}
public sendGetRequest(): Observable<Symbols[]> {
return this.httpClient.get<ApiResponse>(this.REST_API_SERVER)
.pipe(pluck('results'));
}

Angular - TypeError: Converting circular structure to JSON

I'm getting this error at angular service's map method but my returned datas doesn't seem to contain any circular reference, here is my json object:
[{"id":14,
"sender":
{"id":20,"email":"p.martelliere#gmail.com","username":"test5","roles":
["ROLE_USER"],"status":"active","note":"0","points":0,
"devices":[],"job":"Caisse","showJob":false,"notificationsActivated":true,
"connected":true,"tokenConfirm":"","birthDate":[]
},"receiver":
{"id":12,"email":"test2#yopmail.com","username":"test2","tokenConfirm":"",
"job":"g\u00e9rant","showJob":false,"note":"0","points":0,
"roles":["ROLE_USER"],"status":"active","notificationsActivated":true,
"connected":true,"devices":[]
},
"myNeed":"Te ster",
"whatICanGive":"1",
"messages":[],
"status":"active"
}]
Here's my chatRequest angular Entity:
export class NmChatRequest {
// Raw attributes
id : number;
myNeed : string;
whatICanGive : string;
status : string;
createdAt : Date;
updatedAt : Date;
deletedAt : Date;
// x-to-one
id_receiver: number;
constructor(json? : any) {
if (json != null) {
this.id = json.id;
this.myNeed = json.myNeed;
this.whatICanGive = json.whatICanGive;
this.status = json.status;
this.id_receiver = json.id_receiver;
if (json.createdAt != null) {
this.createdAt = new Date(json.createdAt);
}
if (json.updatedAt != null) {
this.updatedAt = new Date(json.updatedAt);
}
if (json.deletedAt != null) {
this.deletedAt = new Date(json.deletedAt);
}
}
}
}
This entity is used to get the object from json.
Here's my ChatRequestService:
/**
* Create the passed nmChatRequest.
*/
add(nmChatRequest : NmChatRequest, token: string) : Observable<NmChatRequest> {
let body = nmChatRequest;
return this.http.post(this.chatUrl, body, {headers: new HttpHeaders({ 'Content-Type': 'application/json', 'X-Auth-Token': token })})
.pipe(
map(response => new NmChatRequest(response)),
catchError(this.handleError)
);
}
What am I missing ?
Thanks to anyone who will take the time to read/answer this question.
I built a stackblitz from the above provided pieces. It seemed to work fine for me if I changed the json string to an object instead of an array.
So no outside brackets:
{"id":14,
"sender":
{"id":20,"email":"p.martelliere#gmail.com","username":"test5","roles":
["ROLE_USER"],"status":"active","note":"0","points":0,
"devices":[],"job":"Caisse","showJob":false,"notificationsActivated":true,
"connected":true,"tokenConfirm":"","birthDate":[]
},"receiver":
{"id":12,"email":"test2#yopmail.com","username":"test2","tokenConfirm":"",
"job":"g\u00e9rant","showJob":false,"note":"0","points":0,
"roles":["ROLE_USER"],"status":"active","notificationsActivated":true,
"connected":true,"devices":[]
},
"myNeed":"Te ster",
"whatICanGive":"1",
"messages":[],
"status":"active"
}
If you are indeed getting an array and not a single object, you may need to modify your code to pass in the first element of the array. Something like this:
map(response => new NmChatRequest(response[0]))
Here is the stackblitz: https://stackblitz.com/edit/angular-wgunjb?file=src%2Fapp%2Fapp.component.ts

How can I use/create dynamic template to compile dynamic Component with Angular 2.0 - from string (JSON)

Based on How can I use/create dynamic template to compile dynamic Component with Angular 2.0 I'm currently facing a timing problem when it comes to dynamic property creation of a component model from a json string that is retrieved from a remote server.
Properties are dynamically created properly within in a new entity - that is later assigned to the empty entity, but the hosting component has been already bound to the empty entity and does not know anything about the dynamically created properties at initialization time. It seems that the creation of the hosting component is already finished when the json result from server arrives asynchronously and a bit later.
As a result a list of empty components without any property data is applied to the page. The number of displayed components is equal to the dynamically added properties. But the dynamic data binding obviously does not know anything about the data attached to the properties.
The forementioned original approach loops through a set of hard wired properties of an entity object to assemble the complete template for each property using the specific propertyname.
Defining a hard wired entity object:
entity = {
code: "ABC123",
description: "A description of this Entity"
};
Assembling a dynamic template string looping through properties of entity:
import {Injectable} from "#angular/core";
#Injectable()
export class DynamicTemplateBuilder {
public prepareTemplate(entity: any, useTextarea: boolean){
let properties = Object.keys(entity);
let template = "<form >";
let editorName = useTextarea
? "text-editor"
: "string-editor";
properties.forEach((propertyName) =>{
template += `
<${editorName}
[propertyName]="'${propertyName}'"
[entity]="entity"
></${editorName}>`;
});
return template + "</form>";
}
}
My approach tries to deal with a full configurable approach:
Json string
{
"code": {
"id": "ADRESSE-UPDATE-001",
"componentType": "text-editor",
"rows": 5,
"cols": 25,
"value": "Hello !"
},
"description": {
"id": "ADRESSE-UPDATE-002",
"componentType": "string-editor",
"rows": 1,
"cols": 50,
"value": "Please enter some data"
},
"Street": {
"id": "ADRESSE-UPDATE-003",
"componentType": "text-editor",
"rows": 10,
"cols": 100,
"value": "Mainstreet"
},
"City": {
"id": "ADRESSE-UPDATE-004",
"componentType": "text-editor",
"rows": 3,
"cols": 5,
"value": "Hamburg"
}
}
Basically the Json retrieval and property creation is organized as:
import { Injectable } from '#angular/core';
import {Http, Response} from "#angular/http";
import { Headers, RequestOptions } from '#angular/http';
import {IValue, IEntityClassAdvanced, Member} from './dynamic-config-interfaces';
var jsonX;
#Injectable()
export class DynamicConfigBuilder{
constructor(private http: Http)
{
}
getEntity(callback):any{
this.callConfigApi(callback);
}
callConfigApi(callback:any) {
jsonX = null;
var content = { "Action": "REQUEST-FOR-CONFIG", "Type": 'CONFIG', "Raw":""};
var jsonText = JSON.stringify(content);
let headers = new Headers({ 'Content-Type': 'application/json' });
let options = new RequestOptions({ headers: headers });
this.http.post('http://localhost:9123/tasks/config',jsonText, options)
.map((res: Response) => res.json())
.subscribe((message: string) => {
jsonX = JSON.parse(message);
console.log(JSON.stringify(jsonX));
//alert("loaded from server: " + JSON.stringify(jsonX));
var entity: IEntityClassAdvanced = {};
Object.keys(jsonX).forEach(function (key) {
entity[key] = { propertyValue: null };
var val = entity[key];
val.propertyValue = new Member().deserialize(jsonX[key]);
});
callback(entity);
});
}
}
Necessary Interfaces and types are located in a separate file:
import { Injectable} from '#angular/core';
//--- typed nested object from json:
export interface Serializable<T> {
deserialize(input: Object): T;
}
#Injectable()
export class Member implements Serializable<Member> {
id: string;
componentType: string;
rows: number;
cols:number;
value:string;
deserialize(input) {
this.id = input.id;
this.componentType = input.componentType;
this.rows = input.rows;
this.cols = input.cols;
this.value = input.value;
return this;
}
}
//--- dynamic object builder elements
export interface IValue {
propertyValue: Member
}
export interface IEntityClassAdvanced {
[name: string]: IValue;
}
//--- end dynamic object builder
Within the callback method the late assignment occurs:
private entityCallback(entityItem:any)
{
//alert("--->" + JSON.stringify(entityItem));
this.entity = entityItem;
this.refreshContent();
}
The template creation comes with a slightly different flavour:
public prepareTemplate(entity:any, useTextarea: boolean){
let properties = Object.keys(entity);
let template = "<form >";
let editorName = useTextarea
? "otago-text-editor"
: "string-editor";
properties.forEach((propertyName) =>{
// alert(propertyName);
let targetComponent = entity[propertyName]["propertyValue"]["componentType"];
template += `
<${targetComponent}
[propertyName]="'${propertyName}'"
[entity]="entity"
></${targetComponent}>`;
});
return template + "</form>";
}
When trying a hard wired approach using an nested inline object that already exists at compile time the binding works fine:
var json = {
code: {
id: "ADRESSE-UPDATE-001",
componentType: "text-editor",
rows:5,
cols:25,
value:"Hello !"
},
description: {
id: "ADRESSE-UPDATE-002",
componentType: "string-editor",
rows:1,
cols:50,
value:"Please enter some data"
},
firstMember: {
id: "ADRESSE-UPDATE-003",
componentType: "text-editor",
rows:10,
cols:100,
value:"Mainstreet"
},
secondMember: {
id: "ADRESSE-UPDATE-004",
componentType: "text-editor",
rows:3,
cols:5,
value:"Hamburg"
}
};
Any suggestions concerning this generic component creation approach/timing problem appreciated.

How to convert a MongoDB document to JSON Object

I am trying to make a post request with the MongoDB document returned from find query, as the request body in NodeJS.But on the server I'm getting the Error : Invalid JSON. Below is the document that I'm trying to POST
{
"_id" : ObjectId("5739a6bf3f1b41477570dc89"),
"taskCount" : 2,
"study" : "cod",
"phase" : "mansa2",
"rhimeTaskId" : "5739a6bec4567f6e737fd3db",
"recordId" : "5726f3cfc4567f6e737fc3ab",
"recordStudy" : "codstudy",
"recordPhase" : "mansa2",
"recordLanguage" : "Punjabi",
"recordScript" : "Latin",
"_state" : "CodingComplete",
"tasks" : [
{
"physician" : ObjectId("5739a6bd3f1b41477570dc78"),
"stage" : "Coding",
"result" : {
"cod" : "C15",
"feedback" : {
"narrativeLength" : "Adequate",
"positiveSymptomsIncluded" : "Only Positive",
"certainty" : "High"
},
"keywords" : [
"52 yr male, died of food pipe cancer, suffered pain upper abdomen, investigated,FNAC confirmed Cancer, Put on Chemotherapy, multiple cycles, died at home, had fever with chills occasionally"
]
}
},
{
"physician" : ObjectId("5739a6bd3f1b41477570dc79"),
"stage" : "Coding",
"result" : {
"cod" : "C15",
"feedback" : {
"narrativeLength" : "Inadequate",
"positiveSymptomsIncluded" : "Only Positive",
"certainty" : "High"
},
"keywords" : [
"severe pain abdomen, ultrasonography revealed food pipe cancer, chemotherapy given, died"
]
}
}
],
"__v" : 2
}
and here is the code that I wrote to make the POST request
var MongoClient = require('mongodb').MongoClient;
var request = require('request');
var assert = require('assert');
var cmeprovisioning= 'mongodb://localhost:27017/cmeprovisioning';
MongoClient.connect(cmeprovisioning, function(err, db) {
assert.equal(null, err);
var count=0;
console.log("Connected to cmeprovisioning");
var cursor =db.collection('rhimeReport').find(
{"study":"cod","phase":"mansa2","recordStudy":"codstudy",
"recordPhase":"mansa2","_state":"CodingComplete"
});
cursor.each(function(err, doc) {
assert.equal(err, null);
if (doc != null) {
console.dir(doc);
count=count+1;
request({url: "http://cme.host.net:8081/cme-provisioning/update",
method: "POST",json: true,
headers: {"content-type": "application/json"},
json: doc
},function(e,r,b){
console.log("POST Error "+count+" "+e)
console.log("POST Response "+count+" "+r)
console.log("POST BODY "+count+" "+b)
});
} else {
console.log("Some Error : "+err)
}
});
});
I also tried using JSON.stringify(doc), but still got the Invalid JSON error. Is there a way I can use mongo document returned by the find query and convert it to JSON to make the POST request.
I think those ObjectID is what making it an invalid JSON document.
Here's the actual answer:
If you want to convert a mongo object to JSON object.
There's a utility method in every mongo object toJSON
So you can simply do mongoResponseObject.toJSON() on the response object.
e.g.
Products.findById(id).then(res => {
const jsonRes = res.toJSON();
// Here jsonRes is JSON
})
Alternatively you can directly get the JSON object by using the .lean() like this.
Products.findById(id).lean().then(res => {
// Here res is JSON
})
you need to convert object id to string ie.
var result = {
"_id": ObjectId("5739a6bf3f1b41477570dc89"),
"taskCount": 2,
"study": "cod"
};
//now convert to string
result=result._id.toString();
//now you can use the result
Try this,
var cursor =db.collection('rhimeReport').find(
{"study":"cod","phase":"mansa2","recordStudy":"codstudy",
"recordPhase":"mansa2","_state":"CodingComplete"});
cursor.toString();
......
Hope this help.
Try this in robomongo
var cursor = db.getCollection('X').find({},{})
while(cursor.hasNext()) {
print(JSON.stringify(cursor.next()))
}

Grails rest render src/groovy classes from rest controller as JSON and create custom JSON renderer

I am working with grails 2.5.0.
I want to render src/groovy class as JSON and custom JSON. If I perform same with domain classes, its working fine for me. I want same thing with src/groovy classes.
For rendering data with json and custom json I followed this link.
I tried to these thing.
Create pogo class in src/groovy.
class UserDTO {
String username
String lastName
String firstName
String email
}
Created a controller with restful feature.
import grails.converters.JSON
import grails.rest.RestfulController
class RenderDTOController extends RestfulController {
static responseFormats = ['json','pogoshort','pogodetails']
RenderDTOController() {
super(UserDTO)
}
def index() {
respond new UserDTO(username: "vivek", firstName: "Vivek", lastName: "Yadav")
}
}
Made an entry on urlMapping.groovy.
"/vivek"(resources:'renderDTO')
Registered new mime type for custom renderer in resources.groovy.
userPogoDetailsRenderer(JsonRenderer, UserDTO) {
mimeTypes = [new MimeType('application/vnd.grails.rest.sample.pogodetails+json', 'pogodetails')]
namedConfiguration = 'pogodetails'
}
output.
userPogoShortRenderer(JsonRenderer, UserDTO) {
mimeTypes = [new MimeType('application/vnd.grails.rest.sample.pogoshort+json', 'pogoshort')]
namedConfiguration = 'pogoshort'
}
userPogoRenderer(JsonRenderer, UserDTO) {
mimeTypes = [new MimeType('application/json', 'json')]
}
Added new mime type in mime type.
grails.mime.types = [ // the first one is the default format
all : '*/*', // 'all' maps to '*' or the first available format in withFormat
atom : 'application/atom+xml',
css : 'text/css',
csv : 'text/csv',
form : 'application/x-www-form-urlencoded',
html : ['text/html', 'application/xhtml+xml'],
js : 'text/javascript',
json : ['application/json', 'text/json'],
multipartForm: 'multipart/form-data',
rss : 'application/rss+xml',
text : 'text/plain',
hal : ['application/hal+json', 'application/hal+xml'],
xml : ['text/xml', 'application/xml'],
pogodetails : ['application/vnd.grails.rest.sample.pogodetails+json', 'application/json'],
pogoshort : ['application/vnd.grails.rest.sample.pogoshort+json', 'application/json']
]
Added custom marshaller in Bootstrap.groovy.
JSON.createNamedConfig("pogodetails") {
println "pogodetails renderer in bootstrap"
it.registerObjectMarshaller(UserDTO) { UserDTO user ->
final String fullname = [user.firstName, user.lastName].join(' ')
final userMap = [
lastName : user.lastName,
username: user.username,
email : user.email,
]
if (fullname) {
userMap.fullname = fullname
}
userMap
}
}
JSON.createNamedConfig('pogoshort') {
println "pogoshort renderer in bootstrap"
it.registerObjectMarshaller(UserDTO) { UserDTO user ->
println "Coming here in pogoshort renderer"
final userMap = [
lastName : user.lastName,
username: user.username
]
userMap
}
}
While I am running, I am getting exception.
URI
/grails-rest-2.5.0/vivek
Class
org.codehaus.groovy.runtime.typehandling.GroovyCastException
Message
Cannot cast object 'com.vivek.UserDTO#12c671a2' with class 'com.vivek.UserDTO' to class 'grails.converters.JSON'
If I change in controller like this.
respond new UserDTO(username: "vivek", firstName: "Vivek", lastName: "Yadav").encodeAsJSON()
I am able to convert it into JSON format.
Also, If user this syntax.
JSON.use("pogodetails")
respond new UserDTO(username: "vivek", firstName: "Vivek", lastName: "Yadav").encodeAsJSON()
I am also able to render pogo in custom format. but I need it to do as rest full controller is doing for doamin.
Is there any way to do same thing with simple POGO defined in src/groovy directory?
Thanks in advance.