Getting json object data with react - json

I am attempting to pull data out of json like this, which is imported as "values"
{
"content": {
"person": [
{
"name": "Test"
"age" : "24:
}
]
}
}
I am using .map like below but getting the error .default.map is not a function I believe it is because i have objects not arrays, i've tried a bunch of stuff including object.keys but i'm getting errors all over the place, any direction would be appreciated.
import values from './sample.json'
const vals = values.map((myval, index) => {
const items = person.items.map((item, i) => {
return (
<div>{item.name}</div>
)
})
return (
<div>{items}</div>
)
})

I think your data and code have some errors. But after fixing those and also changing the name from 'person' to 'people' if that's what you are after, here's the code that does what you are trying to do:
var data = {
content: {
people: [
{
name: "Test",
age: 24,
},
{
name: "Foo",
age: 25,
},
],
},
};
var App = React.createClass({
render: function () {
var people = data.content.people.map(function (person) {
return <div>{person.name}</div>;
});
return <div>{people}</div>;
},
});
ReactDOM.render(<App />, document.getElementById("app"));
And here's the JSBin for that: https://jsbin.com/coyalec/2/edit?html,js,output
Update: I'm updating the answer with more detailed example. It now deals with data more generically, like it doesn't assume what are the entries of 'contents' and such, but it knows that each type like 'people' or 'pets' are an array.
var data = {
content: {
people: [
{
name: "Test",
age: 24,
},
{
name: "Foo",
age: 25,
},
],
pets: [
{
name: "Sweety",
age: 3,
},
{
name: "Kitty",
age: 5,
},
],
},
};
var App = React.createClass({
render: function () {
// Get the keys in data.content. This will return ['people', 'pets']
var contentKeys = Object.keys(data.content);
// Now start iterating through these keys and use those keys to
// retrieve the underlying arrays and then extract the name field
var allNames = contentKeys.map((t) =>
data.content[t].map((e) => <div>{e.name}</div>)
);
return <div>{allNames}</div>;
},
});
ReactDOM.render(<App />, document.getElementById("app"));
And here's the latest JSBin: https://jsbin.com/coyalec/4/edit?html,js,output

Related

Map JSON for Chartjs with Angular 7

Im trying to map JSON Data to show it in a Bar-Chart. The final Array I need has to look like this:[883, 5925, 17119, 27114, 2758].
Actually, the Array I want to use to set the barChartData (dringlichkeitenValues[])seems to be empty. Sorry for my bad coding skills. Can anyone show me how to solve this Problem?
JSON:
[{
"id": 1,
"value": 883
},
{
"id": 2,
"value": 5925
},
{
"id": 3,
"value": 17119
},
{
"id": 4,
"value": 27144
},
{
"id": 5,
"value": 2758
}]
api.service.ts
getDringlichkeiten(): Observable<IDringlichkeit[]> {
return this.http.get<IDringlichkeit[]>(this.ROOT_URL + '/aufenthalte/dringlichkeit');}
dringlichkeit.ts
export interface IDringlichkeit {
id: number;
value: number;
}
bar-chart.component.ts
export class BarChartComponent implements OnInit {
public dringlichkeitValues:number[] = [];
public dringlichkeiten: IDringlichkeit[];
public barChartLabels:String[] = ["1", "2", "3", "4", "5"];
public barChartData:number[] = this.dringlichkeitValues;
public barChartType:string = 'bar';
constructor(private aufenthaltService: AufenthaltService) {
}
ngOnInit() {
this.loadData();
this.getDringlichkeitValues();
}
loadData(){
this.aufenthaltService.getDringlichkeiten()
.subscribe( data => this.dringlichkeiten = data);
}
getDringlichkeitValues(){
let dringlichkeitValues:number[]=[];
this.dringlichkeiten.forEach(dringlichkeit=>{
dringlichkeitValues.push(dringlichkeit.value)
this.dringlichkeitValues = dringlichkeitValues;
});
return this.dringlichkeitValues;
}
}
UPDATE:
I updated my component but now my Array is still empty after subscribing to the Observable.
bar-chart.component.ts
chart: Chart;
dringlichkeiten: IDringlichkeit[] = [];
constructor(private aufenthaltService: AufenthaltService) {
}
ngOnInit() {
this.aufenthaltService.getDringlichkeiten()
.subscribe( data => {
this.dringlichkeiten = data;
//dringlichkeiten-Array full
console.log(this.dringlichkeiten);
});
//dringlichkeiten-Array empty
console.log(this.dringlichkeiten);
this.chart = new Chart('canvas', {
type: 'bar',
data: {
labels: this.dringlichkeiten.map(x => x.id),
datasets: [
{
label: 'Dringlichkeiten',
data: this.dringlichkeiten.map(x => x.value),
backgroundColor: ['#FF6384', '#4BC0C0', '#FFCE56', '#E7E9ED', '#36A2EB']
}
]
},
});
}
To get the "values" from your JSON array, you can use:
dringlichkeiten.map(x => x.value)
This will get you an array you require, i.e.:
[883, 5925, 17119, 27114, 2758]
You can then pass this array to chartJS for it to render you a chart like so:
this.chart = new Chart('canvas', {
type: 'bar',
data: {
labels: dringlichkeiten.map(x => x.id),
datasets: [
{
label: 'My Bar Chart',
data: dringlichkeiten.map(x => x.value),
backgroundColor: ['red', 'green', 'yellow', 'blue', 'orange']
}
]
},
});
Take a look at this simplified working SlackBlitz example.
Hope this helps!

Try to get key values recursively from JSON in Angular 5

I want to retrieve all the key values from a JSON file. For example in :
{
"total_count": 6,
"incomplete_results": false,
"items": [
{
"url": "https://api.github.com/repos/Samhot/GenIHM/issues/6",
"id": 293237635,
"number": 6,
"title": "Rechercher des documents",
"user": {
"login": "Samhot",
"id": 7148311
]
}
I would like to get :
["total_count", "incomplete_results", "items", "url", "url", "number", "title", "user", "login", "id"]
I have a function which return the content of my JSON in an observable :
getConfig(): Observable<any> {
return this.http.get<any>(this.myURL);
}
After that the data are reformated with .map to get only the keys with the Object.keys() function :
merge()
.pipe(
startWith({}),
switchMap(() => {
return this.getConfig();
}),
map(data => {
return Object.keys(data.items[0]);
}
)
)
.subscribe(data => {
this.dispo = data;
});
My problem is that i get only the keys that are in the level of the JSON I told
(data.items[0]) and not the ascendants or the descendants.
Of course I can create multiple requests but it asks to know in advance the structure of the JSON, what I want is to make it generic ...
How can I do to have an array with with all of my keys regardless of the structure of the JSON ?
Thanks in advance !
You would need to do a recursive function like:
function getDeepKeys(obj) {
const keys = Object.keys(obj);
const childKeys = keys
.map(key => obj[key])
.map(
value =>
Array.isArray(value)
? getDeepKeys(value[0])
: typeof value === "object"
? getDeepKeys(value)
: []
)
.reduce((acc, keys) => [...acc, ...keys], []);
return [...keys, ...childKeys];
}
const obj = {
total_count: 6,
incomplete_results: false,
items: [
{
url: "https://api.github.com/repos/Samhot/GenIHM/issues/6",
id: 293237635,
number: 6,
title: "Rechercher des documents",
user: {
login: "Samhot",
id: 7148311
}
},
{
url: "https://api.github.com/repos/Samhot/GenIHM/issues/6",
id: 293237635,
number: 6,
title: "Rechercher des documents",
user: {
login: "Samhot",
id: 7148311
}
}
]
};
console.log(getDeepKeys(obj));
Which then you would use like map(getDeepKeys). Note that this function assumes all the items in your array have the same schema.

Nested arrays in object json to csv

Im using 'json-csv' library to create a csv from a users arrays with nested objects and arrays.
var users = [
{
subscriptions: [
{
package : {
name: 'Grammar'
},
state: 'EXPIRED',
timerange: {
period : 5550
},
transaction:{
amount: 10000
}
},
{
package : {
name: 'GK'
},
state: 'ACTIVE',
timerange: {
period : 30
},
transaction:{
amount: 10340
}
},
],
account:{
balance: 200
},
name: "Johhy Moe",
email: null,
user_id: "123456789",
username: null,
user_type: "facebook",
id: 3,
createdAt: "2016-07-11T08:02:40.000Z",
updatedAt: "2016-07-11T08:02:40.000Z",
},
{
subscriptions: [
{
package : {
name: 'GK'
},
state: 'EXPIRED',
timerange: {
period : 42
},
transaction:{
amount: 5252
}
},
{
package : {
name: 'MATH'
},
state: 'ACTIVE',
timerange: {
period : 25
},
transaction:{
amount: 200
}
}
],
account:{
balance: 1500
},
name: "John Doe",
email: null,
user_id: "123456789",
username: null,
user_type: "facebook",
id: 7,
createdAt: "2016-07-29T06:44:18.000Z",
updatedAt: "2016-07-29T06:44:18.000Z"
},
]
Now i want the generated csv to be like this
USERID,NAME,FBID,ACCOUNT,SUBSCRIPTION,PRICE,STATE,TIMEPERIOD
3,Johhy Moe,123456789,200,Grammar,10000,EXPIRED,5550
3,Johhy Moe,123456789,200,GK,10340,ACTIVE,30
7,John Doe,123456789,1500,GK,5252,EXPIRED,30
7,John Doe,123456789,1500,MATH,200,ACTIVE,25
As you see if there are two objects inside subscription array for each user, i want to repeat that user again but with different subscription data.
I've thought of using the library because my users array can go up to thousands of users with hundreds of subscription.
And i'm at a loss to what i should do.
my Code:
var options= {
fields : [
{
name : 'id',
label : 'USERID'
},
{
name : 'name',
label : 'Name'
},
{
name : 'user_id',
label : 'FBID'
},
{
name : 'account.balance',
label : 'ACCOUNT'
},
{
name: '',
label: 'Subscription'
}
]
}
var source = es.readArray(users)
source
.pipe(jsoncsv.csv(options))
.pipe(res)
I dont want to use a library also. So if someone could provide me with a resource to make my own csv file with strings and also using streams , that would be great. Thanks!!
This will solve your problem. Now you just have to change console.log to fs and write to your file.
var json2csv = function (json, listKeys) {
var str = "";
var prefix = "";
for (var i = 0; i < listKeys.length; i++) {
str += prefix + json[listKeys[i]];
prefix = ",";
}
return str;
};
var async = require('async');
var csvData = ['USERID,NAME,FBID,ACCOUNT,SUBSCRIPTION,PRICE,STATE,TIMEPERIOD'];
async.each(users, function (user, callback) {
var csvRow1 = {
USERID: user.id,
NAME: user.name,
FBID: user.user_id,
ACCOUNT: user.account.balance
};
async.each(user.subscriptions, function (subscription, callback) {
var csvRow2 = JSON.parse(JSON.stringify(csvRow1));
csvRow2.SUBSCRIPTION = subscription.package.name;
csvRow2.PRICE = subscription.transaction.amount;
csvRow2.STATE = subscription.state;
csvRow2.TIMEPERIOD = subscription.timerange.period;
csvData.push(json2csv(csvRow2, ['USERID', 'NAME', 'FBID', 'ACCOUNT', 'SUBSCRIPTION', 'PRICE', 'STATE', 'TIMEPERIOD']));
callback(null);
}, function (err) {
callback(err);
});
}, function (err) {
if (err) {
// return err;
} else {
// return csvData;
}
});

ImmutableJS: Convert List to indexed Map

This question is about Immutable.js library.
I have a List<T>, where T is {name: string, id: number}. I want to convert it to Map<number, T>, with id of T to the keys. Using standard method toMap gives me a Map with sequential indexes, and there is no way to hook there. And no method like indexBy or other. how to do that?
You can do it with a reducer like this:
function indexBy(iterable, searchKey) {
return iterable.reduce(
(lookup, item) => lookup.set(item.get(searchKey), item),
Immutable.Map()
);
}
var things = Immutable.fromJS([
{id: 'id-1', lol: 'abc'},
{id: 'id-2', lol: 'def'},
{id: 'id-3', lol: 'jkl'}
]);
var thingsLookup = indexBy(things, 'id');
thingsLookup.toJS() === {
"id-1": { "id": "id-1", "lol": "abc" },
"id-2": { "id": "id-2", "lol": "def" },
"id-3": { "id": "id-3", "lol": "jkl" }
};

JSON stringify in Node JS not serializing array of objects

I am using sails.js (node js framework).
I am trying to JSON.stringify one of the objects, but when I do that it omits one of the fields (rooms array below).
Here is what console.log(object) gives me:
[ { rooms: [ [Object], [Object] ],
state: '53df76c278999310248072c6',
name: 'Sydney Center',
menuItems: null,
createdAt: Mon Aug 04 2014 23:42:08 GMT+0300 (Jerusalem Summer Time),
updatedAt: Mon Aug 04 2014 23:42:08 GMT+0300 (Jerusalem Summer Time),
id: '53dff0205c89c03428a31cee' },
{ rooms: [ [Object], [Object], [Object] ],
state: '53df76c278999310248072c6',
createdAt: Mon Aug 04 2014 23:43:21 GMT+0300 (Jerusalem Summer Time),
menuItems: null,
name: 'Batata Center',
updatedAt: Mon Aug 04 2014 23:51:11 GMT+0300 (Jerusalem Summer Time),
id: '53dff06a5c89c03428a31cf3' } ]
JSON output (rooms are not printed):
[
{
"state": "53df76c278999310248072c6",
"name": "Sydney Center",
"menuItems": null,
"createdAt": "2014-08-04T20:42:08.885Z",
"updatedAt": "2014-08-04T20:42:08.885Z",
"id": "53dff0205c89c03428a31cee"
},
{
"state": "53df76c278999310248072c6",
"createdAt": "2014-08-04T20:43:21.999Z",
"menuItems": null,
"name": "Batata Center",
"updatedAt": "2014-08-04T20:51:11.740Z",
"id": "53dff06a5c89c03428a31cf3"
}
]
What might be the problem?
The rooms data seems to be fine.
For the complete function (SailsJS):
getCentersData: function(req, res) {
sails.log.info('Teacher.getCentersData: ', req.user.id);
var userId = req.user.id;
async.auto({
teacher: function(cb) {
Teacher.findOne({ user: userId }).populate('centers').exec(cb);
},
centers: [
'teacher', function(cb, results) {
var allCentersIds = _.pluck(results.teacher.centers, 'id');
Center.findById(allCentersIds).populate('rooms').exec(cb);
}
],
rooms: [
'centers', function(cb, results) {
var allRoomIds = [];
_.each(results.centers, function(center) {
allRoomIds = _.union(allRoomIds, _.pluck(center.rooms, 'id'));
});
Room.findById(allRoomIds).populate('children').exec(cb);
}
],
children: [
'rooms', function(cb, results) {
var allChildrenIds = [];
_.each(results.rooms, function (room) {
allChildrenIds = _.union(allChildrenIds, _.pluck(room.children, 'id'));
});
Child.findById(allChildrenIds).populate('parents').exec(cb);
}
],
parentUsers: ['children', function(cb, results) {
var allParentIds = [];
_.each(results.children, function (child) {
allParentIds = _.union(allParentIds, _.pluck(child.parents, 'id'));
});
Parent.findById(allParentIds).populate('user').exec(cb);
}],
map: ['parentUsers', function (cb, results) {
// map children to parents
var parentsMapper = _.indexBy(results.parentUsers, 'id');
var childrenMappedToParents = _.map(results.children, function (child) {
var _child = child.toObject();
_child.parents = _.map(child.parents, function (parent) {
return parentsMapper[parent.id];
});
return _child;
});
var childrenMapper = _.indexBy(childrenMappedToParents, 'id');
// map rooms to children
var roomsMappedToChildren = _.map(results.rooms, function (room) {
var _room = room.toObject();
_room.children = _.map(room.children, function (child) {
return childrenMapper[child.id];
});
return _room;
});
var roomsMapper = _.indexBy(roomsMappedToChildren, 'id');
// map center to rooms
var centersMappedToRooms = _.map(results.centers, function (center) {
var _center = center.toObject();
_center.rooms = _.map(center.rooms, function (room) {
return roomsMapper[room.id];
});
return _center;
});
sails.log.info('centersMappedToRooms',centersMappedToRooms ); // includes rooms array
sails.log.info('centersMappedToRooms json: ', JSON.stringify(centersMappedToRooms)); // does not include rooms array
return cb(null, centersMappedToRooms);
}]
}, function(err, results) {
if (err) {
return res.serverError(err);
}
// added prints
sails.log.info("results.map: ", results.map);
sails.log.info("JSON.stringify(results.map): ", JSON.stringify(results.map)); // same same, does not print the rooms array
return res.json(results.map);
});
},
EDITED
Schema:
schema: true,
attributes: {
name: {
type: 'string',
required: true,
minLength: 5
},
// Many-To-Many association with Teacher model
teachers: {
collection: 'teacher',
via: 'centers'
},
// One-To-Many association with State model
state: {
model: 'state'
},
// One-To-Many association with Room model
rooms: {
collection: 'room',
via: 'center'
},
// One-To-One association with Principal model
principal: {
model: 'principal'
},
menuItems: {
type: 'array',
defaultsTo: null
}
},
Because Waterline queries return models, not plain javascript objects, they have additional properties and functions on them. One of these is an overridden toJSON() function which removes attributes that have not been populated. What seems to be happening here is that you are attaching objects to a parent model which doesn't know it has children that have been populated so it strips off the values.
The reasoning behind this is so that if you query for all Users and don't populate Rooms you don't get an incorrect result showing an empty rooms array.
I'm not sure what all you are manipulating here but the reason it works if you _.cloneDeep is because it removes the custom toJSON field. This is the recommend strategy when you are mutating a parent object from a query like this.