Change representation of JSON object to explicit key/value format - javascript

I have the following JSON:
{
"temperature": "22.2",
"power": "6",
"current": "156"
}
and I need to convert it to this explicit structure:
{
"key": "temperature",
"value": "22.2"
},
{
"key": "power",
"value": "6"
},
{
"key": "current",
"value": "156"
}
Is there an elegant, simple and quick way to do this?
Best, thx

var newStructure = Object.keys(obj).map(function(key){
return {'key':key, 'value':obj[key]}
})
Example
var obj = {
"temperature": "22.2",
"power": "6",
"current": "156"
}
var arr = Object.keys(obj).map(function(key){return {'key':key,'value':obj[key]}})
console.log(arr)

Object.hashToKeyValuePairs = function (hash) {
var ret = [];
for (var i in hash)
ret.push({ key: i, value: hash[i]});
return ret;
};
// example
document.body.innerHTML = JSON.stringify(
Object.hashToKeyValuePairs({ a: 1, b: 2, c: 3 })
);

Related

How can I dynamically remove a parent in JSON with JS?

With some JavaScript, how can I transform a JSON from:
{
"d": {
"__count": "13",
"results": [
{
"__metadata": {
"id": "123"
},
"COAST": "East",
"STATUS": "done",
"COLOR": "blue",
}
]
}
}
TO
{
"__count": "13",
"data": [
{
"__metadata": {
"id": "123"
},
"COAST": "East",
"STATUS": "done",
"COLOR": "blue",
}
]
}
Basically removing the extra "d" parent and renaming results to data? I am using this in the context of vue-table in VueJS.
Assumed that you have the json saved in a variable 'data':
data = data.d
data.data = data.results
delete data.results
This function will do it.
function transform(json) {
var obj = JSON.parse(json);
obj.d.data = obj.d.result;
delete obj.d.result;
return JSON.stringify(obj.d);
}
One solution is to unserialize your JSON to have an object (JSON.parse()). Then to serialize only what you need (JSON.stringify()).
You can use a loop.
var res = [];
for(var k in jsonData){
res.push(jsonData[k]);
}
var jsonData = {
"d": {
"__count": "13",
"results": [
{
"__metadata": {
"id": "123"
},
"COAST": "East",
"STATUS": "done",
"COLOR": "blue",
}
]
}
};
console.log(jsonData);
var res = [];
for(var k in jsonData){
res.push(jsonData[k]);
}
console.log("result:");
console.log(res);

Convert json response to table

I'm trying to convert json response to array which accepts my table (component from devextreme). I'm trying to do that on angular 6. Json looks like that:
"data": [
{
"type": "A",
"date": "2018-05",
"value": "153"
},
{
"type": "B",
"date": "2018-05",
"value": "888"
},
{
"type": "C",
"date": "2018-05",
"value": "999"
},
{
"type": "D",
"date": "2018-05",
"value": "555"
},
{
"type": "A",
"date": "2018-06",
"value": "148"
},
{
"type": "B",
"date": "2018-06",
"value": "222"
},
{
"type": "C",
"date": "2018-06",
"value": "555"
},
{
"type": "D",
"date": "2018-06",
"value": "666"
},
{
"type": "A",
"date": "2018-07",
"value": "156"
},
{
"type": "B",
"date": "2018-07",
"value": "111"
},
{
"type": "C",
"date": "2018-07",
"value": "333"
},
{
"type": "D",
"date": "2018-07",
"value": "999"
}
],
"number": "111-111"
}
]
And I need to transform it to this format:
[{
month: '2018-05',
A: 153,
B: 888,
C: 999,
D: 555
},
{
month: '2018-06',
A: 148,
B: 222,
C: 555,
D: 666
},
{
month: '2018-07',
A: 156,
B: 111,
C: 333,
D: 999
}]
Number of types can change (so there could be A and B only for example). Can anybody help me with that ? I'm using this component to present data at website https://js.devexpress.com/Demos/WidgetsGallery/Demo/DataGrid/SimpleArray/Angular/Light/
This is how I would approach your problem:
1) Get the list of types and dates from your data source. We make use of JavaScript's Set to store the values so that the values will be unique (without duplicates).
The value from date will be considered as the unique key for each object in the result array, and the type will be the other properties of the result ('A', 'B', 'C', and 'D')
2) Once we have those 2 arrays, we will iterate through the original list to generate the object. The values of properties A, B, C, D are populated by filtering the date and type from the original list.
const list = {"data":[{"type":"A","date":"2018-05","value":"153"},{"type":"B","date":"2018-05","value":"888"},{"type":"C","date":"2018-05","value":"999"},{"type":"D","date":"2018-05","value":"555"},{"type":"A","date":"2018-06","value":"148"},{"type":"B","date":"2018-06","value":"222"},{"type":"C","date":"2018-06","value":"555"},{"type":"D","date":"2018-06","value":"666"},{"type":"A","date":"2018-07","value":"156"},{"type":"B","date":"2018-07","value":"111"},{"type":"C","date":"2018-07","value":"333"},{"type":"D","date":"2018-07","value":"999"}],"number":"111-111"};
// const dates = [...new Set(list.data.map(item => item.date))];
const dates = Array.from(list.data.map(item => item.date));
console.log(dates);
// const types = [...new Set(list.data.map(item => item.type))];
const types = Array.from(list.data.map(item => item.type));
console.log(types)
const res = dates.map(date => {
const obj = {};
types.map(type => {
obj[type] = list.data.filter(item => item.date === date && item.type === type)[0].value;
});
obj.date = date;
return obj;
});
console.log(res);
Given that your input is
let input = {
"data": [
{
"type": "A",
"date": "2018-05",
"value": "153"
},
{
"type": "B",
"date": "2018-05",
"value": "888"
},
{
"type": "C",
"date": "2018-05",
"value": "999"
},
{
"type": "D",
"date": "2018-05",
"value": "555"
},
{
"type": "A",
"date": "2018-06",
"value": "148"
},
{
"type": "B",
"date": "2018-06",
"value": "222"
},
{
"type": "C",
"date": "2018-06",
"value": "555"
},
{
"type": "D",
"date": "2018-06",
"value": "666"
},
{
"type": "A",
"date": "2018-07",
"value": "156"
},
{
"type": "B",
"date": "2018-07",
"value": "111"
},
{
"type": "C",
"date": "2018-07",
"value": "333"
},
{
"type": "D",
"date": "2018-07",
"value": "999"
}
],
"number": "111-111"
};
You can do this to get the required result in the output variable
let output = [];
input.data.forEach(function (item) {
const type = item.type;
const date = item.date;
const value = item.value;
let newlyCreated = false;
let objForMonth = output.find(x => x.month == date);
if (!objForMonth) {
newlyCreated = true;
objForMonth = {};
objForMonth.month = date;
}
objForMonth[type] = value;
if (newlyCreated) {
output.push(objForMonth);
} else {
let indexToWriteTo = output.findIndex(x => x.month == date);
output[indexToWriteTo] = objForMonth;
}
});
You can try like this
TS
let finalArray = [];
let valueA: string = null;
let valueB: string = null;
let valueC: string = null;
// Here data is a variable which contain your JSON data
for(let i = 0; i < data.length; i++) {
if (data.type === 'A') {
valueA = data[i].value;
}
if (data.type === 'B') {
valueB = data[i].value;
}
if (data.type === 'C') {
valueC = data[i].value;
}
if (data.type === 'D') {
finalArray.push({
month: data[i].date
A: valueA,
B: valueB,
C: valueC,
D: data[i].value
});
}
}
console.log(finalArray);
Let me know if it is working or not.

Create new array with another structure in Javascript

I want to create a new array based on an original array but with merged data.
Every name key need to have merged date+time (format: YYYY-MM-DD HH:MM) with merged scores. All unique datetimes need to be available as key for each name.
ARRAY ORIGINAL:
"data": [{
"name": "A",
"history": [{
"created": "2017-05-16 00:00:00",
"score": "1"
},
{
"created": "2017-05-16 00:01:10",
"score": "1"
},
{
"created": "2017-05-16 00:01:30",
"score": "1"
}
]
},
{
"name": "B",
"history": [{
"created": "2017-05-16 00:01:00",
"score": "1"
}]
}
]
ARRAY THAT I WANT:
{
[A]: {
"2017-05-16 00:00": 1,
"2017-05-16 00:01": 2
},
[B]: {
"2017-05-16 00:00": 0,
"2017-05-16 00:01": 1
}
}
I hope you guys can help me out. I can't even think of an efficiƫnt way to do this, unfortunately. I tried to solve this issue with 5 foreach statements with no luck :(
You could use two arrays for names and times as closure and generate for all names and times a property with zero value.
var data = { data: [{ name: "A", history: [{ created: "2017-05-16 00:00:00", score: "1" }, { created: "2017-05-16 00:01:10", score: "1" }, { created: "2017-05-16 00:01:30", score: "1" }] }, { name: "B", history: [{ created: "2017-05-16 00:01:00", score: "1" }] }] },
result = data.data.reduce(function (names, times) {
return function (r, a) {
if (!r[a.name]) {
r[a.name] = {};
times.forEach(function (time) {
r[a.name][time] = 0;
});
names.push(a.name);
}
a.history.forEach(function (o) {
var time = o.created.slice(0, 16);
if (times.indexOf(time) === -1) {
names.forEach(function (name) {
r[name][time] = 0;
});
times.push(time);
}
r[a.name][time] += +o.score;
});
return r;
};
}([], []), {});
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
You have to create an object not an array, As arrays cannot have a key-value pair in javascript. There is no associative array concept in javascript. You have to use objects in javascript for that.
Here is how you can do what you are trying to achieve using objects.
value = {
"data": [{
"name": "A",
"history": [{
"created": "2017-05-16 00:00:00",
"score": "1"
},
{
"created": "2017-05-16 00:01:10",
"score": "1"
},
{
"created": "2017-05-16 00:01:30",
"score": "1"
}
]},
{
"name": "B",
"history": [{
"created": "2017-05-16 00:01:00",
"score": "1"
}]
}]
};
var result ={};
value.data.forEach(function(v){
var score = {};
for(var i=0;i<v.history.length;i++){
score[v.history[i].created] = v.history[i].score;
}
result[v.name] = score;
});
console.log(result);
Now you can access data as result.A or result[A] and result.B or result[B]
SNIPPET
value = {
"data": [{
"name": "A",
"history": [{
"created": "2017-05-16 00:00:00",
"score": "1"
},
{
"created": "2017-05-16 00:01:10",
"score": "1"
},
{
"created": "2017-05-16 00:01:30",
"score": "1"
}
]
},
{
"name": "B",
"history": [{
"created": "2017-05-16 00:01:00",
"score": "1"
}]
}
]
};
var result = {};
value.data.forEach(function(v) {
var score = {};
for (var i = 0; i < v.history.length; i++) {
score[v.history[i].created] = v.history[i].score;
}
result[v.name] = score;
});
console.log(result);

Remove empty string in nested json object via AngularJS

I have an nested json object in which I need to remove empty values and create new json which should contain only data objects.
json file:
myData = [{
"id": 1,
"values": [{
"value": ""
}]
}, {
"id": 2,
"values": [{
"value": 213
}]
}, {
"id": 3,
"values": [{
"value": ""
}, {
"value": ""
}, {
"value": "abc"
}]
},{
"id": 4,
"values": [{
"value": ""
}]
},{
"id": 33,
"values": [{
"value": "d"
}]
}];
Output should be:
myNewData = [{
"id": 2,
"values": [{
"value": 213
}]
}, {
"id": 3,
"values": [{
"value": "abc"
}]
},{
"id": 33,
"values": [{
"value": "d"
}]
}];
So far I have created this:
angular.module('myapp',[])
.controller('test',function($scope){
$scope.myData = [{
"id": 1,
"values": [{
"value": ""
}]
}, {
"id": 2,
"values": [{
"value": 213
}]
}, {
"id": 3,
"values": [{
"value": ""
}, {
"value": ""
}, {
"value": "abc"
}]
},{
"id": 4,
"values": [{
"value": ""
}]
},{
"id": 33,
"values": [{
"value": "d"
}]
}];
})
.filter('filterData',function(){
return function(data) {
var dataToBePushed = [];
data.forEach(function(resultData){
if(resultData.values && resultData.values != "")
dataToBePushed.push(resultData);
});
return dataToBePushed;
}
});
Html:
<div ng-app="myapp">
<div ng-controller="test">
<div ng-repeat="data in myData | filterData">
Id:{{ data.id }}
</br>
Values: {{ data.values }}
</div>
</div>
</div>
I am not able to access and remove value inside values object. Right now i am simply showing the data using ng-repeat but i need to create a new json file for that.
You work with the array in your AngularJS Controller doing Array.prototype.map() and Array.prototype.filter(). Map all objects doing a filter to exclude the items with empty values item.values.value, and than a filter to get the array elements that have values with value:
var myData = [{"id": 1,"values": [{ "value": ""}]}, {"id": 2,"values": [{"value": 213}]}, {"id": 3,"values": [{"value": ""}, {"value": ""}, {"value": "abc"}]}, {"id": 4,"values": [{"value": ""}]}, {"id": 33,"values": [{"value": "d"}]}],
myDataFiltered = myData
.map(function (item) {
item.values = item.values.filter(function (itemValue) {
return itemValue.value;
});
return item;
})
.filter(function (item) {
return item.values.length;
});
console.log(myDataFiltered);
.as-console-wrapper { max-height: 100% !important; top: 0; }
ES6:
myDataFiltered = myData
.map(item => {
item.values = item.values.filter(itemValue => itemValue.value);
return item;
})
.filter(item => item.values.length);
Here you go with a multiple for-loop.
myData = [{
"id": 1,
"values": [{
"value": ""
}]
}, {
"id": 2,
"values": [{
"value": 213
}]
}, {
"id": 3,
"values": [{
"value": ""
}, {
"value": ""
}, {
"value": "abc"
}]
},{
"id": 4,
"values": [{
"value": ""
}]
},{
"id": 33,
"values": [{
"value": "d"
}]
}];
function clone(obj){ return JSON.parse(JSON.stringify(obj));}
var result = [];
for(var i = 0; i < myData.length; i++){
var current = clone(myData[i]);
for(var j = 0; j < current.values.length; j++){
if(current.values[j].value == null || current.values[j].value == ""){
current.values.splice(j, 1);
j--;
}
}
if(current.values.length > 0) result.push(current);
}
console.log(myData);
console.log(result);
If you want to delete them completely, you can iterate over the array like this;
angular.forEach($scope.myData, function(data){
for(var i=0; i < data.values.length; i++){
if(data.values[i] !== ""){
break;
}
delete data;
}
});
The if statement checks all values in the array, and breaks if it's not equal to "", otherwise if all values are = "" it deletes the object.
Hope it helps!
Here's a recursive function to do the job.
This will only work if myData is an array and the value inside it or its children is a collection of object.
var myData = [{"id": 1, "values": [{"value": ""}] }, {"id": 2, "values": [{"value": 213 }] }, {"id": 3, "values": [{"value": ""}, {"value": ""}, {"value": "abc"}] },{"id": 4, "values": [{"value": ""}] },{"id": 6, "values": ""},{"id": 33, "values": [{"value": "d"}] }];
function removeEmptyValues (arr) {
var res = false;
/* Iterate the array */
for (var i = 0; i < arr.length; i++) {
/* Get the object reference in the array */
var obj = arr[i];
/* Iterate the object based on its key */
for (var key in obj) {
/* Ensure the object has the key or in the prototype chain */
if (obj.hasOwnProperty(key)) {
/* So, the object has the key. And we want to check if the object property has a value or not */
if (!obj[key]) {
/*
If it has no value (null, undefined, or empty string) in the property, then remove the whole object,
And reduce `i` by 1, to do the re-checking
*/
arr.splice(i--, 1);
/* Amd set whether the removal occurance by setting it to res (result), which we will use for the next recursive function */
res = true;
/* And get out from the loop */
break;
}
/* So, the object has a value. Let's check whether it's an array or not */
if (Array.isArray(obj[key])) {
/* Kay.. it's an array. Let's see if it has anything in it */
if (!obj[key].length) {
/* There's nothing in it !! Remove the whole object again */
arr.splice(i--, 1);
/* Amd set whether the removal occurance by setting it to res (result), which we will use for the next recursive function */
res = true;
/* Yes.. gets out of the loop */
break;
}
/*
Now this is where `res` is being used.
If there's something removed, we want to re-do the checking of the whole object
*/
if ( removeEmptyValues(obj[key]) ) {
/* Something has been removed, re-do the checking */
i--;
}
}
}
}
}
return res;
}
removeEmptyValues (myData);
Try this:
var myData = [{"id": 1,"values": [{ "value": ""}]}, {"id": 2,"values": [{"value": 213}]}, {"id": 3,"values": [{"value": ""}, {"value": ""}, {"value": "abc"}]}, {"id": 4,"values": [{"value": ""}]}, {"id": 33,"values": [{"value": "d"}]}]
let result=[],p=[];
myData.filter(el => {
p=[];
el.values.filter(k => {k.value != '' ? p.push({value : k.value}) : null});
if(p.length) result.push({id : el.id, values : p})
})
console.log('result', result);
You are going to right way but need some more operation like this :
angular.module('myapp',[])
.controller('test',function($scope){
$scope.myData = [{
"id": 1,
"values": [{
"value": ""
}]
}, {
"id": 2,
"values": [{
"value": 213
}]
}, {
"id": 3,
"values": [{
"value": ""
}, {
"value": ""
}, {
"value": "abc"
}]
},{
"id": 4,
"values": [{
"value": ""
}]
},{
"id": 33,
"values": [{
"value": "d"
}]
}];
})
.filter('filterData',function($filter){
return function(data) {
var dataToBePushed = [];
data.forEach(function(resultData){
var newValues=resultData;
var hasData=$filter('filter')(resultData.values,{value:'!'},true);
if(resultData.values && resultData.values.length>0 && hasData.length>0){
newValues.values=hasData;
dataToBePushed.push(newValues);
}
});
debugger;
return dataToBePushed;
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myapp">
<div ng-controller="test">
<div ng-repeat="data in myData | filterData:''">
Id:{{ data.id }}
</br>
Values: {{ data.values }}
</div>
</div>
</div>

Transform structure of array of objects

I have data like -
var data = [{"DefaultZone":[{"key":"stream0","value":100},
{"key":"stream1","value":50},
{"key":"stream2","value":10}
]},
{"Zone 1":[{"key":"stream0","value":120},
{"key":"stream1","value":55},
{"key":"stream2","value":15}
]}
]
and wanted to transform it like -
var data = [{"key": "stream0", "values":[{"x":"DefaultZone","y":100}, {"x":"Zone 1","y":120}]},
{"key": "stream1", "values":[{"x":"DefaultZone","y":50}, {"x":"Zone 1","y":55}]},
{"key": "stream2", "values":[{"x":"DefaultZone","y":10}, {"x":"Zone 1","y":15}]}
];
using JavaScript(ES6). Any help would be highly appreciated..
Here is the first way that came to mind:
var data = [{
"DefaultZone": [
{ "key": "stream0", "value": 100 },
{ "key": "stream1", "value": 50 },
{ "key": "stream2", "value": 10 }]
}, {
"Zone 1": [
{ "key": "stream0", "value": 120 },
{ "key": "stream1", "value": 55 },
{ "key": "stream2", "value": 15 }]
}];
let working = data.reduce((p, c) => {
let x = Object.keys(c)[0];
c[x].forEach(v => {
if (!p[v.key]) p[v.key] = [];
p[v.key].push({ x: x, y: v.value });
});
return p;
}, {});
let output = Object.keys(working).map(v => ({ key: v, values: working[v] }));
console.log(output);
Further reading:
the array .reduce() method
the Object.keys() method
the array .forEach() method
the array .map() method
Although I like nnnnnn's answer, here is another one, using only the Object.keys() method:
var data = [{
"DefaultZone": [{
"key": "stream0",
"value": 100
}, {
"key": "stream1",
"value": 50
}, {
"key": "stream2",
"value": 10
}]
}, {
"Zone 1": [{
"key": "stream0",
"value": 120
}, {
"key": "stream1",
"value": 55
}, {
"key": "stream2",
"value": 15
}]
}]
final = {}
data.forEach(function(x) {
Object.keys(x).forEach(function(y) {
x[y].forEach(function(z) {
if (!final[z['key']]) final[z['key']] = [];
final[z['key']].push({
'x': y,
'y': z['value']
})
})
})
})
answer = []
Object.keys(final).forEach(function(x) {
answer.push({
'key': x,
values: final[x]
})
})
console.log(answer)

Categories