Using JSON API Serializer to create more complicated JSON - json

The examples here don't go nearly far enough in explaining how to produce a more complicated structure...
If I want to end up with something like:
{
"data": {
"type": "mobile_screens",
"id": "1",
"attributes": {
"title": "Watch"
},
"relationships": {
"mobile_screen_components": {
"data": [
{
"id": "1_1",
"type": "mobile_screen_components"
},
{
"id": "1_2",
"type": "mobile_screen_components"
},
...
]
}
}
},
"included": [
{
"id": "1_1",
"type": "mobile_screen_components",
"attributes": {
"title": "Featured Playlist",
"display_type": "shelf"
},
"relationships": {
"playlist": {
"data": {
"id": "938973798001",
"type": "playlists"
}
}
}
},
{
"id": "938973798001",
"type": "playlists",
"relationships": {
"videos": {
"data": [
{
"id": "5536725488001",
"type": "videos"
},
{
"id": "5535943875001",
"type": "videos"
}
]
}
}
},
{
"id": "5536725488001",
"type": "videos",
"attributes": {
"duration": 78321,
"live_stream": false,
"thumbnail": {
"width": 1280,
"url":
"http://xxx.jpg?pubId=694940094001",
"height": 720
},
"last_published_date": "2017-08-09T18:26:04.899Z",
"streams": [
{
"url":
"http://xxx.m3u8",
"mime_type": "MP4"
}
],
"last_modified_date": "2017-08-09T18:26:27.621Z",
"description": "xxx",
"fn__media_tags": [
"weather",
"personality"
],
"created_date": "2017-08-09T18:23:16.830Z",
"title": "NOAA predicts most active hurricane season since 2010",
"fn__tve_authentication_required": false
}
},
...,
]
}
what is the most simple data structure and serializer I can set up?
I get stumped after something like:
const mobile_screen_components = responses.map((currentValue, index) => {
id[`id_${index}`];
});
const dataSet = {
id: 1,
title: 'Watch',
mobile_screen_components,
};
const ScreenSerializer = new JSONAPISerializer('mobile_screens', {
attributes: ['title', 'mobile_screen_components'],
mobile_screen_components: {
ref: 'id',
}
});
Which only gives me:
{
"data": {
"type": "mobile_screens",
"id": "1",
"attributes": { "title": "Watch" },
"relationships": {
"mobile-screen-components": {
"data": [
{ "type": "mobile_screen_components", "id": "1_0" },
{ "type": "mobile_screen_components", "id": "1_1" },
{ "type": "mobile_screen_components", "id": "1_2" },
{ "type": "mobile_screen_components", "id": "1_3" },
{ "type": "mobile_screen_components", "id": "1_4" },
{ "type": "mobile_screen_components", "id": "1_5" }
]
}
}
}
}
I have no idea how to get the "included" sibling to "data." etc.

So, the question is:
what is the most simple data structure and serializer I can set up?
Below is the simplest object that can be converted to JSON similar to JSON in the question using jsonapi-serializer:
let dataSet = {
id: '1',
title: 'Watch',
mobile_screen_components: [
{
id: '1_1',
title: 'Featured Playlists',
display_type: 'shelf',
playlists: {
id: 938973798001,
videos: [
{
id: 5536725488001,
duration: 78321,
live_stream: false
},
{
id: 5535943875001,
duration: 52621,
live_stream: true
}
]
}
}
]
};
To serialize this object to JSON API, I used the following code:
let json = new JSONAPISerializer('mobile_screen', {
attributes: ['id', 'title', 'mobile_screen_components'],
mobile_screen_components: {
ref: 'id',
attributes: ['id', 'title', 'display_type', 'playlists'],
playlists: {
ref: 'id',
attributes: ['id', 'videos'],
videos: {
ref: 'id',
attributes: ['id', 'duration', 'live_stream']
}
}
}
}).serialize(dataSet);
console.log(JSON.stringify(json, null, 2));
The first parameter of JSONAPISerializer constructor is the resource type.
The second parameter is the serialization options.
Each level of the options equals to the level of the nested object in serialized object.
ref - if present, it's considered as a relationships.
attributes - an array of attributes to show.

Introduction
First of all we have to understand the JSON API document data structure
[0.1] Refering to the top level (object root keys) :
A document MUST contain at least one of the following top-level
members:
data: the document’s “primary data”
errors: an array of error objects
meta: a meta object that contains non-standard meta-information.
A document MAY contain any of these top-level members:
jsonapi: an object describing the server’s implementation
links: a links object related to the primary data.
included: an array of resource objects that are related to the primary data and/or each other (“included resources”).
[0.2]
The document’s “primary data” is a representation of the resource or
collection of resources targeted by a request.
Primary data MUST be either:
a single resource identifier object, or
null, for requests that target single resources
an array of resource identifier
objects, or an empty array ([]), for reqs. that target
collections
Example
The following primary data is a single resource object:
{
"data": {
"type": "articles",
"id": "1",
"attributes": {
// ... this article's attributes
},
"relationships": {
// ... this article's relationships
}
}
}
In the (jsonapi-serializer) documentation : Available serialization option (opts argument)
So in order to add the included (top-level member) I performed the following test :
var JsonApiSerializer = require('jsonapi-serializer').Serializer;
const DATASET = {
id:23,title:'Lifestyle',slug:'lifestyle',
subcategories: [
{description:'Practices for becoming 31337.',id:1337,title:'Elite'},
{description:'Practices for health.',id:69,title:'Vitality'}
]
}
const TEMPLATE = {
topLevelLinks:{self:'http://example.com'},
dataLinks:{self:function(collection){return 'http://example.com/'+collection.id}},
attributes:['title','slug','subcategories'],
subcategories:{ref:'id',attributes:['id','title','description']}
}
let SERIALIZER = new JsonApiSerializer('pratices', DATASET, TEMPLATE)
console.log(SERIALIZER)
With the following output :
{ links: { self: 'http://example.com' },
included:
[ { type: 'subcategories', id: '1337', attributes: [Object] },
{ type: 'subcategories', id: '69', attributes: [Object] } ],
data:
{ type: 'pratices',
id: '23',
links: { self: 'http://example.com/23' },
attributes: { title: 'Lifestyle', slug: 'lifestyle' },
relationships: { subcategories: [Object] } } }
As you may observe, the included is correctly populated.
NOTE : If you need more help with your dataSet, edit your question with the original data.

Related

Fetching for each element within array in MongoDb

I have an 'users' collection. I store id's of users I follow in 'following' field.
{
"_id": {
"$oid": "5eab360253ec352e3cc791d6"
},
"email": "koray#gmail.com",
"password": "81dc9bdb52d04dc20036dbd8313ed055",
"following": ["5ea8879dfc286e1154a866cb", "5ea8879dfc286e1154a866c"],
"posts": [{
"head": "deneme header",
"body": "deneme body",
"is_private": false
}]
}
I want to get posts of users I follow as well as posts belogs to me but can't manage to pull it off.
You can use $lookup with custom pipeline and fetch documents from the same collection:
db.collection.aggregate([
{ $match: { _id: "5eab360253ec352e3cc791d6" } },
{
$lookup: {
from: "collection",
let: { following_users: "$following" },
pipeline: [
{ $match: { $expr: { $in: [ "$_id", "$$following_users" ] } } },
{ $project: { posts: 1 } }
],
as: "following_posts"
}
}
])
Mongo Playground

Mongoose Model for Nested Array JSON

I need to create a Mongoose model for the below nested JSON array. The issue I am facing is TLSM01 is a dynamic Key and I am unable to specify it in the model. If I mention entities alone and pass all the json objects as string it is storing as [object] and not data.
"entities": [
{
"TLSM01": [
{
"01": {
"Name": "Light",
"Properties": [
{
"state": [
{
"type": "boolean",
"propertyMode": "actuator"
}
],
"brightness": [
{
"type": "integer",
"propertyMode": "actuator"
}
]
}
]
}
}
]
}
Mongoose Model:
var thingsSchema = ({
"uuid": String,
"things": String,
"manufacturerName": String,
"manufacturerId": String,
"osName": String,
"hardwareVersion": String,
"firmwareVersion": String,
"entity": [{String}]
})
Store data in key-value pair
"entities": [
{
keyName:'TLSM01',
data: [
{
"01": {
"Name": "Light",
"Properties": [
{
"state": [
{
"type": "boolean",
"propertyMode": "actuator"
}
],
"brightness": [
{
"type": "integer",
"propertyMode": "actuator"
}
]
}
]
}
}
]
}
]
Mongoose Model:
var thingsSchema = ({
"uuid": String,
"things": String,
"manufacturerName": String,
"manufacturerId": String,
"osName": String,
"hardwareVersion": String,
"firmwareVersion": String,
"entity": [{_id:false,keyName:{type:String},data:[]}]
})
1.I think you need something structured like this:
2.See how the light value is an array...within the object - must use key value paring in Mongo and ensure you model Json Object can be mapped to you mongoose database - hence you use you data model to input data - so this should work if you augment it..
const blogSchema = new Schema({
name:{
type:String,
require: true
},
heat:{
type:Number,
Require:true
},
moisture:{
type:Number,
Require:true
},
light:{
green:{type:Number, Require:true},
red:{type:Number, Require:true},
blue:{type:Number, Require:true},
white:{type:Number, Require:true}
},
body:{
type:String,
require: true
}
},{timeStamps:true});

Ember Multitple belongTo relationships not working with JSONAPI

I have the following json api document:
{
"data": [
{
"type": "haves",
"id": "2708f443-0857-4ae9-9935-9aa4b4e9f721",
"attributes": {
"quantity": 1
},
"relationships": {
"card": {
"data": {
"type": "cards",
"id": "3be08f31-3361-404c-9977-23535ed837f3"
}
}
}
}
],
"included": [
{
"type": "cards",
"id": "3be08f31-3361-404c-9977-23535ed837f3",
"attributes": {
"name": "Name"
},
"relationships": {
"set": {
"data": {
"type": "sets",
"id": "0fec70de-02e0-4646-bdcf-f86acea90d23"
}
}
}
},
{
"type": "sets",
"id": "0fec70de-02e0-4646-bdcf-f86acea90d23",
"attributes": {
"name": "Name"
}
}
]
}
With the following ember models:
// app/models/have.js
export default DS.Model.extend({
quantity: DS.attr('number'),
minPrice: DS.attr('number'),
account: DS.belongsTo('account'),
card: DS.belongsTo('card')
});
// app/models/set.js
export default DS.Model.extend({
name: DS.attr('string'),
cards: DS.hasMany('card')
});
// app/models/card.js
export default DS.Model.extend({
name: DS.attr('string'),
set: DS.belongsTo('set'),
haves: DS.hasMany('have')
});
And a custom inflector rule:
inflector.irregular('have', 'haves');
When I load the json document with this structure though, I can't seem to do something like have.card.set.name in my template when I iterate this jsonapi document. I'm guessing my jsonapi structure is incorrect. What am I missing? I don't get any errors in my chrome console or in the ember server running. When I load Ember Inspector, I see the set model under Data.

evaluating json object returned from controller and attaching it to prepopulate attribute of tokeninput

I am using loopjs tokeninput in a View. In this scenario I need to prePopulate the control with AdminNames for a given Distributor.
Code Follows :
$.getJSON("#Url.Action("SearchCMSAdmins")", function (data) {
var json=eval("("+data+")"); //doesnt work
var json = {
"users": [
eval("("+data+")") //need help in this part
]
}
});
$("#DistributorCMSAdmin").tokenInput("#Url.Action("SearchWithName")", {
theme: "facebook",
preventDuplicates: true,
prePopulate: json.users
});
There is successful return of json values to the below function. I need the json in the below format:
var json = {
"users":
[
{ "id": "1", "name": "USER1" },
{ "id": "2", "name": "USER2" },
{ "id": "3", "name": "USER3" }
]
}

Loading TreeStore with JSON that has different children fields

I am having a JSON data like below.
{
"divisions": [{
"name": "division1",
"id": "div1",
"subdivisions": [{
"name": "Sub1Div1",
"id": "div1sub1",
"schemes": [{
"name": "Scheme1",
"id": "scheme1"
}, {
"name": "Scheme2",
"id": "scheme2"
}]
}, {
"name": "Sub2Div1",
"id": "div1sub2",
"schemes": [{
"name": "Scheme3",
"id": "scheme3"
}]
}
]
}]
}
I want to read this into a TreeStore, but cannot change the subfields ( divisions, subdivisions, schemes ) to be the same (eg, children).
How can achieve I this?
When nested JSON is loaded into a TreeStore, essentially the children nodes are loaded through a recursive calls between TreeStore.fillNode() method and NodeInterface.appendChild().
The actual retrieval of each node's children field is done within TreeStore.onNodeAdded() on this line:
dataRoot = reader.getRoot(data);
The getRoot() of the reader is dynamically created in the reader's buildExtractors() method, which is what you'll need to override in order to deal with varying children fields within nested JSON. Here is how it's done:
Ext.define('MyVariJsonReader', {
extend: 'Ext.data.reader.Json',
alias : 'reader.varijson',
buildExtractors : function()
{
var me = this;
me.callParent(arguments);
me.getRoot = function ( aObj ) {
// Special cases
switch( aObj.name )
{
case 'Bill': return aObj[ 'children' ];
case 'Norman': return aObj[ 'sons' ];
}
// Default root is `people`
return aObj[ 'people' ];
};
}
});
This will be able to interpret such JSON:
{
"people":[
{
"name":"Bill",
"expanded":true,
"children":[
{
"name":"Kate",
"leaf":true
},
{
"name":"John",
"leaf":true
}
]
},
{
"name":"Norman",
"expanded":true,
"sons":[
{
"name":"Mike",
"leaf":true
},
{
"name":"Harry",
"leaf":true
}
]
}
]
}
See this JsFiddle for fully working code.