How to extract json Response? - json

Someone told me.
obj is a JSON response.
obj = { title: 'ABCD', _key: '-KX9Cwwuc2FjxcG-SNY0' }
I can get ABCD using console.log(obj["title”]).
How about complex case?
obj = { '-KXu3irrOjUtcejm4VF3':
{ gold: 0,
title: ‘xxxx09x#gmail.com',
uketuke: 0,
user: ‘xxxx09x#gmail.com' },
'-KXu3vLo7--JeVYC9fJa': { title: ‘JUMP' },
'-KXu3yRZgFlDcS8BZ7e1': { title: 'JUMP1' } }
In this case, how can I get the user entity?
By the way like this obj["title”] presentation, I think this should be ECMA standard,
please let me know where reference is?

If you knew the key then it's quite easy. For example:
obj = {
'-KXu3irrOjUtcejm4VF3': {
gold: 0,
title: 'xxxx09x#gmail.com',
uketuke: 0,
user: 'xxxx09x#gmail.com'
},
'-KXu3vLo7--JeVYC9fJa': { title: 'JUMP' },
'-KXu3yRZgFlDcS8BZ7e1': { title: 'JUMP1' }
}
var user_key = '-KXu3irrOjUtcejm4VF3'
user = obj[user_key].user
"xxxx09x#gmail.com"
However if you did not know the key of object in which the user exists then the following function can help with asymptotic complexity O(n):
function getUser(obj) {
for (var key in obj) {
// skip loop if the property is from prototype
if (!obj.hasOwnProperty(key)) continue;
if (typeof obj[key].user !== undefined) {
return obj[key].user;
}
}
}
getUser(obj)
"xxxx09x#gmail.com"
And finally there is something I used in one of projects: jsonpath
$..user
would return all user from your obj. This way you can go quite far with a complicated json IMHO.

Need to do some corrections :
To access the property value from this JSON response var obj = { title: 'ABCD', _key: '-KX9Cwwuc2FjxcG-SNY0' } you have to use dot(.) operator instead of [].
If you will use obj[title] it will give you an error :
Uncaught ReferenceError: title is not defined(…)
If you will use obj.title it will give you an output :
ABCD
So, as per the complex case :
First thing : Strings should be wrapped in double quotes.
Invalid JSON :
var obj = {
'-KXu3irrOjUtcejm4VF3': {
gold: 0,
title: 'xxxx09x#gmail.com',
uketuke: 0,
user: 'xxxx09x#gmail.com'
},
'-KXu3vLo7--JeVYC9fJa': { title: ‘JUMP' },
'-KXu3yRZgFlDcS8BZ7e1': { title: 'JUMP1' }
};
Valid JSON :
var obj = {
"-KXu3irrOjUtcejm4VF3": {
"gold": 0,
"title": "abc#gmail.com",
"uketuke": 0,
"user": "def#gmail.com"
},
"-KXu3vLo7--JeVYC9fJa": {
"title": "JUMP"
},
"-KXu3yRZgFlDcS8BZ7e1": {
"title": "JUMP1"
}
}

Related

How to access child json object inside React componnent

I am trying to access values from the following in my react component.
sample JSON response
additionalinfo: {
totalCount : 10,
missingmetersregisters: {
missingCounts: {
mscsMeters: 0,
mdmsMeters: 0,
mscsRegisters: 0,
mdmsRegisters: 0
}
},
intervaldatadifference: {
intervaldatadifferencecount: 2
}
}
I am able to access totalCount like this {additionalinfo.totalCount} working fine.
But when I try to access intervaldatadifferencecount like this throwing exception/error in react component.
{additionalinfo.intervaldatadifference.intervaldatadifferencecount}
// error case
is there any way to handle this flat single JSON object? I am not an expert in react.
I also tried to iterate create individual iteration like this.
Object.keys(additionalinfo.missingmetersregisters.missingCounts).map((key) => {
console.log(key) // this returned keys only and I need values also
})
or is there any better way to do this?
Thanks
Object.keys(additionalinfo.missingmetersregisters.missingCounts).map((key)
=> { console.log(key) // this returned keys only and I need values also })
To get values use
Object.keys(additionalinfo.missingmetersregisters.missingCounts).map((key) => {
console.log(key) // key
console.log(additionalinfo.missingmetersregisters.missingCounts[key]) //value
})
Hi you can use it like this
Object.entries(additionalinfo.missingmetersregisters.missingCounts).map(data=>{console.log('data',data[0],data[1])});
//data[0] will be the key and data[1] will be the value
Accessing the objects inside object is straight forward thing. Only that there could be scenarios where one of the objects in the chain could be missing then you need to be cautious while accessing.
Optional chaining can be used when there's such scenario and you are not sure whether all the keys in the object will be available or not. Having said that this is a new feature and please make sure to check the compatibility check in the docs before using in your application.
Below is an example for the same
let data = {
additionalinfo: {
totalCount: 10,
missingmetersregisters: {
missingCounts: {
mscsMeters: 0,
mdmsMeters: 0,
mscsRegisters: 0,
mdmsRegisters: 0,
},
},
intervaldatadifference: {
intervaldatadifferencecount: 2,
},
},
}
console.log(data.additionalinfo?.totalCount)
console.log(data.additionalinfo?.intervaldatadifference?.intervaldatadifferencecount)
console.log(data?.additionalinfo?.missingmetersregisters?.test)
console.log(data?.additionalinfo?.intervaldatadifferenc?.intervaldatadifferencecount)
If this is not compatible with your supported devices or technology versions then there's another way you can access, please refer below for the same.
This is another way of accessing object chain when you know some of the levels in the object chain might be missing.
let data = {
additionalinfo: {
totalCount: 10,
missingmetersregisters: {
missingCounts: {
mscsMeters: 0,
mdmsMeters: 0,
mscsRegisters: 0,
mdmsRegisters: 0,
},
},
intervaldatadifference: {
intervaldatadifferencecount: 2,
},
},
}
const {additionalinfo = {}} = data;
const {intervaldatadifference = {}} = additionalinfo;
const {missingmetersregisters = {}} = additionalinfo;
const {intervaldatadifferenc = {}} = additionalinfo;
console.log(additionalinfo.totalCount)
console.log(intervaldatadifference.intervaldatadifferencecount)
console.log(missingmetersregisters.test)
console.log(intervaldatadifferenc.intervaldatadifferencecount)
Here I have created a utility to list all the key-value pairs of an object by passing the object as a param to the utility.
let data = {
additionalinfo: {
totalCount: 10,
missingmetersregisters: {
missingCounts: {
mscsMeters: 0,
mdmsMeters: 0,
mscsRegisters: 0,
mdmsRegisters: 0,
},
},
intervaldatadifference: {
intervaldatadifferencecount: 2,
},
},
}
const listAll = obj => {
for (let [key, value] of Object.entries(obj)) {
console.log(`${key} - ${JSON.stringify(value)}`)
}
}
listAll(data.additionalinfo.missingmetersregisters.missingCounts)
Hope this helps.

Segregate and arrange data in specific format in Angular?

Hi I am developing Angular 5 application. I am trying to arrange data in specific format. I have json data. I want to convert it to specific format.
Below is the specific format.
this.nodes = [
{
name: 'root1',
children: [
{ name: 'child1' }
]
},
{
name: 'root2',
hasChildren: true
},
{
name: 'root3'
}
];
Below is my data.
{
"userid":"e75792f8-cfea-460e-aca2-07a778c92a7c",
"tenantid":"00000000-0000-0000-0000-000000000000",
"username":"karthik",
"emailaddress":"john#krsars.onmicrosoft.com",
"isallowed":false,
"userroles":[
{
"userroleid":"b81e63d1-09da-4aa0-af69-0f086ddb20b4",
"userid":"e75792f8-cfea-460e-aca2-07a778c92a7c",
"roleid":"85d2f668-f523-4b64-b177-b1a78db74234",
"tenantappid":1,
"validfrom":"2018-01-24T00:00:00",
"validto":"2018-01-24T00:00:00",
"isactive":true,
}
]
}
From the above data, I am trying to convert. From the above data each key/value pair I am converting it to format above given, For example, "userid":"e75792f8-cfea-460e-aca2-07a778c92a7c" I want to make it as
{
name: 'userid',
children: [
{ name: 'e75792f8-cfea-460e-aca2-07a778c92a7c' }
]
}
So below I is my code.
for (let key in results) {
if(results[key] instanceof Array){
this.nodes+=
name:key,
hasChildren: true
}+"}"
}
else
{
this.nodes+="{"+name=key,
children: [
{ name: results[key] }
]+"}"
}
}
Finally When i tried to display my data in console.
console.log(this.nodes);
Above my code does not work. Can someone help me to make this work? Any help would be appreciated. Thank you.
Here is a working example. Just to show you which way to go:
doIt() {
let results = JSON.parse('{"userid":"e75792f8-cfea-460e-aca2-07a778c92a7c","tenantid":"00000000-0000-0000-0000-000000000000","username":"karthik","emailaddress":"john#krsars.onmicrosoft.com","isallowed":false,"userroles":[{"userroleid":"b81e63d1-09da-4aa0-af69-0f086ddb20b4","userid":"e75792f8-cfea-460e-aca2-07a778c92a7c","roleid":"85d2f668-f523-4b64-b177-b1a78db74234","tenantappid":1,"validfrom":"2018-01-24T00:00:00","validto":"2018-01-24T00:00:00","isactive":true}]}');
const nodes = [];
for (const key in results) {
if (results[key] instanceof Array) {
const containerTyp2 = {name: '', hasChildren: false};
containerTyp2.name = key;
containerTyp2.hasChildren = true;
nodes.push(containerTyp2);
} else {
const object = {name: ''};
const containerTyp1 = {name: '', children: []};
object.name = key;
containerTyp1.name = key;
containerTyp1.children.push(object);
nodes.push(containerTyp1);
}
}
console.log('nodes: ', nodes);
}

Merging 2 REST endpoints to a single GraphQL response

New to graphQL, I'm Using the following schema:
type Item {
id: String,
valueA: Float,
valueB: Float
}
type Query {
items(ids: [String]!): [Item]
}
My API can return multiple items on a single request of each type (A & B) but not for both, i.e:
REST Request for typeA : api/a/items?id=[1,2]
Response:
[
{"id":1,"value":100},
{"id":2,"value":30}
]
REST Request for typeB : api/b/items?id=[1,2]
Response:
[
{"id":1,"value":50},
{"id":2,"value":20}
]
I would like to merge those 2 api endpoints into a single graphQL Response like so:
[
{
id: "1",
valueA: 100,
valueB: 50
},
{
id: "2",
valueA: 30,
valueB: 20
}
]
Q: How would one write a resolver that will run a single fetch for each type (getting multiple items response) making sure no unnecessary fetch is triggered when the query is lacking the type i.e:
{items(ids:["1","2"]) {
id
valueA
}}
The above example should only fetch api/a/items?id=[1,2] and the graphQL response should be:
[
{
id: "1",
valueA: 100
},
{
id: "2",
valueA: 30
}
]
So I assumed you are using JavaScript as the language. What you need in this case is not to use direct query, rather use fragments
So the query would become
{
items(ids:["1","2"]) {
...data
}}
fragment data on Item {
id
valueA
}
}
Next in the resolver we need to access these fragments to find the fields which are part of the fragment and then resolve the data based on the same. Below is a simple nodejs file with same
const util = require('util');
var { graphql, buildSchema } = require('graphql');
var schema = buildSchema(`
type Item {
id: String,
valueA: Float,
valueB: Float
}
type Query {
items(ids: [String]!): [Item]
}
`);
var root = { items: (source, args, root) => {
var fields = root.fragments.data.selectionSet.selections.map(f => f.name.value);
var ids = source["ids"];
var data = ids.map(id => {return {id: id}});
if (fields.indexOf("valueA") != -1)
{
// Query api/a/items?id=[ids]
//append to data;
console.log("calling API A")
data[0]["valueA"] = 0.12;
data[1]["valueA"] = 0.15;
}
if (fields.indexOf("valueB") != -1)
{
// Query api/b/items?id=[ids]
//append to data;
console.log("calling API B")
data[0]["valueB"] = 0.10;
data[1]["valueB"] = 0.11;
}
return data
},
};
graphql(schema, `{items(ids:["1","2"]) {
...data
}}
fragment data on Item {
id
valueA
}
`, root).then((response) => {
console.log(util.inspect(response, {showHidden: false, depth: null}));
});
If we run it, the output is
calling API A
{ data:
{ items: [ { id: '1', valueA: 0.12 }, { id: '2', valueA: 0.15 } ] } }
If we change the query to
{
items(ids:["1","2"]) {
...data
}}
fragment data on Item {
id
valueA
valueB
}
}
The output is
calling API A
calling API B
{ data:
{ items:
[ { id: '1', valueA: 0.12, valueB: 0.1 },
{ id: '2', valueA: 0.15, valueB: 0.11 } ] } }
So this demonstrates how you can avoid call for api A/B when their fields are not needed. Exactly as you had asked for

How can I create an array from a json object?

My json looks like this, it consists of objects and a few other properties:
let jsonobject = {
"one":{ id:'Peter'},
"two":{ id:'John'},
"three":{ id:'Ko'},
"id":1,
"name":'Jack'
}
I want to convert this to an array with lodash or something, the result would be:
[{ id:'Peter'},
{ id:'John'},
{ id:'Ko'}]
So I can use _.values(jsonobject) but how can I ditch the id and the name property which are obviously no objects? I want a compact solution and/or use lodash.
(1) Get all values for the outer object, (2) filter non object items.
_.filter(_.values(jsonobject), _.isObject)
Or alternatively the chained variant:
_(jsonobject).values().filter(_.isObject).value()
You can simply use filter with an isObject predicate to get the values.
var result = _.filter(jsonobject, _.isObject);
let jsonobject = {
"one": {
id: 'Peter'
},
"two": {
id: 'John'
},
"three": {
id: 'Ko'
},
"id": 1,
"name": 'Jack'
};
var result = _.filter(jsonobject, _.isObject);
console.log(result);
body > div { min-height: 100%; top: 0; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.js"></script>
You can loop over the key in your object and store those that are objects in an array.
var obj = {
"one":{ id:'Peter'},
"two":{ id:'John'},
"three":{ id:'Ko'},
"id":1,
"name":'Jack'
};
var arr = [];
for(var key in obj){
if(typeof obj[key] === 'object'){
arr.push(obj[key]);
}
}
console.log(arr);

Ember Data: Saving relationships

I need to save a deep object to the server all at once and haven't been able to find any examples online that use the latest ember data (1.0.0-beta.4).
For example, with these models:
(jsfiddle)
App.Child = DS.Model.extend({
name: DS.attr('string'),
age: DS.attr('number'),
toys: DS.hasMany('toy', {async:true, embedded:'always'}),
});
App.Toy = DS.Model.extend({
name: DS.attr('string'),
child: DS.belongsTo('child')
});
And this code:
actions: {
save: function(){
var store = this.get('store'),
child, toy;
child = store.createRecord('child', {
name: 'Herbert'
});
toy = store.createRecord('toy', {
name: 'Kazoo'
});
child.set('toys', [toy]);
child.save();
}
}
It only saves the JSON for the child object but not any of the toys -- not even side loaded:
{
child: {
age: null
name: "Herbert"
}
}
Do I have to manually save the toys too? Is there anyway that I can have it send the following JSON to the server:
{
child: {
age: null
name: "Herbert",
toys: [{
name: "Kazoo"
}]
}
}
Or
{
child: {
age: null
name: "Herbert",
toys: [1]
}
}
See JSFiddle: http://jsfiddle.net/jgillick/LNXyp/2/
The answers here are out of date. Ember Data now supports embedded records, which allows you to do exactly what you're looking to do, which is to get and send the full object graph in one big payload. For example, if your models are set up like this:
App.Child = DS.Model.extend({
name: DS.attr('string'),
age: DS.attr('number'),
toys: DS.hasMany('toy')
});
App.Toy = DS.Model.extend({
name: DS.attr('string'),
child: DS.belongsTo('child')
});
You can define a custom serializer for your Child model:
App.ChildSerializer = DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, {
attrs: {
toys: {embedded: 'always'}
}
});
This tells Ember Data that you'd like 'toys' to be included as part of the 'child' payload. Your HTTP GET response from your API should look like this:
{
"child": {
"id": 1,
"name": "Todd Smith",
"age": 5,
"toys": [
{"id": 1, "name": "boat"},
{"id": 2, "name": "truck"}
]
}
}
And when you save your model, Ember Data will send this to the server:
{
"child":{
"name":"Todd Smith",
"age":5,
"toys":[
{
"id":"1",
"name":"boat",
"child":"1"
},
{
"id":"2",
"name":"truck",
"child":"1"
}
]
}
}
Here is a JSBin that demonstrates this.
http://emberjs.jsbin.com/cufaxe/3/edit?html,js,output
In the JSbin, when you click the 'Save' button, you'll need to use the Dev Inspector to view the request that's sent to the server.
toys can't be both async and embedded always, those are contradicting options. Embedded only exists on the active model serializer currently.
toys: DS.hasMany('toy', {embedded:'always'})
the toys are a ManyToOne relationship, and since the relationship exists on the belongsTo side it is more efficient to save the relationship during the toy's save. That being said, if you are creating it all at once, then want to save it in one big chunk that's where overriding comes into play.
serializeHasMany: function(record, json, relationship) {
var key = relationship.key;
var relationshipType = DS.RelationshipChange.determineRelationshipType(record.constructor, relationship);
if (relationshipType === 'manyToNone' || relationshipType === 'manyToMany' ||
relationshipType === 'manyToOne') {
json[key] = get(record, key).mapBy('id');
// TODO support for polymorphic manyToNone and manyToMany relationships
}
},
And your save should be like this
var store = this.get('store'),
child, toy;
child = store.createRecord('child', {
name: 'Herbert'
});
toy = store.createRecord('toy', {
name: 'Kazoo'
});
child.get('toys').pushObject(toy);
child.save().then(function(){
toy.save();
},
function(err){
alert('error', err);
});
I needed a deep object, instead of a side-loaded one, so based on kingpin2k's answer, I came up with this:
DS.JSONSerializer.reopen({
serializeHasMany: function(record, json, relationship) {
var key = relationship.key,
property = Ember.get(record, key),
relationshipType = DS.RelationshipChange.determineRelationshipType(record.constructor, relationship);
if (property && relationshipType === 'manyToNone' || relationshipType === 'manyToMany' ||
relationshipType === 'manyToOne') {
// Add each serialized nested object
json[key] = [];
property.forEach(function(item, index){
json[key].push(item.serialize());
});
}
}
});
Now when you call child.serialize(), it will return this object:
{
child: {
name: "Herbert",
toys: [
{
name: 'Kazoo'
}
]
}
}
Which is what I need. Here's the jsfiddle with it in action: http://jsfiddle.net/jgillick/LNXyp/8/