traversing through json nodes - javascript

Is it possible to traverse through all the nodes and find the wanted field from a complex json whose level is not predetermined
{
"_index": "test",
"_type": "news",
"_source": {
"partnerName": "propertyFile 9",
"relatedSources": "null",
"entityCount": "50",
"Categories": {
"Types": {
"Events": [{
"count": 1,
"term": "Time",
"Time": [{
"term": "Dec 9",
"Dec_9": [{
"count": 1,
"term": "2012"
}]
}]
}, {
"count": 4,
"term": "News",
"News": [{
"term": "Germany",
"Germany": [{
"count": 1,
"term": "Election"
}],
"currency": "Euro (EUR)"
}, {
"term": "Egypt",
"Egypt": [{
"count": 1,
"term": "Revolution"
}]
}]
}]
}
}
}
}
I could get in to the first level , bt how do I go to second level if the field name is not present in the first level. This is how I started it. http://jsfiddle.net/W8qhA/1/

I hope this will solve your problem. There is some function and also a little explanation. Hope that helps you out.
Traverse all the Nodes of a JSON Object Tree with JavaScript

I whipped up a function that will work on an object of the structure you presented. If there are multiple keys of the same name it will simply return the first one it encounters.
var findDeepKey = function(obj, key){
var results = [];
if (typeof obj !== 'object') return null;
for (var k in obj) {
if (k === key) return obj[k];
}
for (var k in obj) {
if (typeof obj[k] === 'object') {
if (obj[k].length) {
for (var i = 0, il = obj[k].length; i < il; i++) {
results.push(findDeepKey(obj[k][i], key));
}
} else {
for (var kk in obj[k]) {
if (kk === key) return obj[k][kk];
results.push(findDeepKey(obj[k][kk], key));
}
}
}
}
for (var i = 0, il = results.length; i < il; i++) {
if (results[i] !== null) return results[i];
}
return null;
};
See demo

You can use http://james.newtonking.com/projects/json-net.aspx

Related

how to transform a source object into another object?

I am trying to transform an object or in other words I am trying change text of an object.
I have two object one is source and another is mapped object.using mapped object I want o transform the source object.
example
source object
{
"links": {
"Offering": {
"id":"offering-id",
"iconUrl": "",
"links": [
{
"text": "School",
"id":"school-id",
"onclickUrl": "https://www.school.com/school/"
},
{
"text": "happy",
"onclickUrl": "https://www.happy.com/help/",
"id":"happy-id"
}
]
},
"luck": {
"iconUrl": "",
"id":"hospital-id",
"links": [
{
"text": "Student",
"id":"student-id",
"onclickUrl": "https://www.student.com/school/"
}
]
}
}
}
mapped -object
let mappingObj = {
"hospital-id":"hospital-change",
"school-id":"school-change-xx",
"offering-id":"Offering-changes-map",
"happy-id":"happy-cs",
"student-id":"nnnnnn"
}
expectedout output
let expectedOutput = {
"links": {
"Offering-changes-map": {
"id":"offering-id",
"iconUrl": "",
"links": [
{
"text": "school-change-xx",
"id":"school-id",
"onclickUrl": "https://www.school.com/school/"
},
{
"text": "happy-cs",
"onclickUrl": "https://www.happy.com/help/",
"id":"happy-id"
}
]
},
"hospital-change": {
"iconUrl": "",
"id":"hospital-id",
"links": [
{
"text": "nnnnnn",
"id":"student-id",
"onclickUrl": "https://www.student.com/school/"
}
]
}
}
}
I have id's in source obj same id's are present in mapped obj.using this I want to change the text of all properties and keys.
I tried like that here is my whole code
https://jsbin.com/zaxoyineme/edit?js,console,output
let result = {};
function recursiveFn(Obj){
for(let i in Obj){
result[mappingObj[Obj[i].id] || i]=Obj[i];
if(typeof Obj[i]==="object"){
console.log('--obj--');
recursiveFn(Obj[i]);
}else if(Object.prototype.toString.call(Obj[i]) === '[object Array]'){
console.log('--Array--');
for(var k =0 ;k<Obj[i].length;k++){
Obj[i].text = result[mappingObj[Obj[i].id] || Obj[i].text]
}
}
}
}
for(let i in Obj){
result[mappingObj[Obj[i].id] || i]=Obj[i];
if(typeof Obj[i]==="object"){
console.log('----');
recursiveFn(Obj[i])
}else if(Object.prototype.toString.call(Obj[i]) === '[object Array]'){
console.log('--Array--');
for(var k =0 ;k<Obj[i].length;k++){
Obj[i].text = result[mappingObj[Obj[i].id] || Obj[i].text]
}
}
}
console.log(JSON.stringify(result))
I am using recession to get the expected output.but I am not able to get the expected output
Your code is way to complicated for what you are trying to do. From What I understood this should probably do your job.
let Obj = {
"links": {
"Offering": {
"id":"offering-id",
"iconUrl": "",
"links": [
{
"text": "School",
"id":"school-id",
"onclickUrl": "https://www.school.com/school/"
},
{
"text": "happy",
"onclickUrl": "https://www.happy.com/help/",
"id":"happy-id"
}
]
},
"luck": {
"iconUrl": "",
"id":"hospital-id",
"links": [
{
"text": "Student",
"id":"student-id",
"onclickUrl": "https://www.student.com/school/"
}
]
}
}
}
let mappingObj = {
"hospital-id":"hospital-change",
"school-id":"school-change-xx",
"offering-id":"Offering-changes-map",
"happy-id":"happy-cs",
"student-id":"nnnnnn"
}
// expected output
let expectedOutput = {
"links": {
"Offering-changes-map": {
"id":"offering-id",
"iconUrl": "",
"links": [
{
"text": "school-change-xx",
"id":"school-id",
"onclickUrl": "https://www.school.com/school/"
},
{
"text": "happy-cs",
"onclickUrl": "https://www.happy.com/help/",
"id":"happy-id"
}
]
},
"hospital-change": {
"iconUrl": "",
"id":"hospital-id",
"links": [
{
"text": "nnnnnn",
"id":"student-id",
"onclickUrl": "https://www.student.com/school/"
}
]
}
}
}
let result = {};
let midResult = {};
function updateObject (Obj) {
let i = 0;
let parseArray = Object.keys(Obj.links);
for (i =0; i < parseArray.length; i++) {
let id = parseArray[i]
let matchingId = mappingObj[Obj.links[id].id]
midResult[matchingId] = Object.assign({}, Obj.links[id])
}
}
updateObject(Obj);
result.links = Object.assign({}, midResult)
console.log(result)

Normalize JSON to a custom schema

I have an array of objects with the following format
var arr = [
{
"productId": "123456",
"productName": "Test Product 1",
"description": [
"This is delicious",
"Suitable for vegetarian"
],
"attributes": {
"internalId": "091283"
"category": "Dairy"
},
"order": 1
}
];
And I am trying to map into something like below
[
[{
{
"name": "productId",
"value": "123456"
},
{
"name": "productName",
"value": "Test Product 1"
},
{
"name": "description",
"value": ["This is delicious", "Suitable for vegetarian"]
},
{
"name": "attributes",
"value": {
{
"name": "internalId",
"value": "091283"
},
{
"name": "category",
"value": "Dairy"
}
}
},
{
"name": "order",
"value": 1
}
}]
]
I tried mapping simple properties before going further and now stuck at getting only the last property of each object in the loop.
Suppose I don't know what are the format of incoming data and how can I normalize the JSON object to the format I want?
normalizeJson = (array) => {
for(i = 0; i < array.length; i++){
normalizedJson[i] = {};
Object.keys(array[i]).forEach(key => {
if (array[i][key] && typeof array[i][key] === "object") {
// normalizeJson(obj[key]);
// console.log(key + ' is object');
return;
} else {
o = {};
o["name"] = key;
o["value"] = array[i][key];
normalizedJson[i] = o;
// normalizedJson[i]["name"] = key;
// normalizedJson[i].value = array[i][key];
// console.log(key);
return;
}
});
}
console.log(normalizedJson);
};
Or is there any library I can use in order to achieve this?
Try this
var obj = [
{
productId: "123456",
productName: "Test Product 1",
description: ["This is delicious", "Suitable for vegetarian"],
attributes: {
internalId: "091283",
category: "Dairy",
},
order: 1,
},
];
function normalizeObject(obj) {
var result = [];
if (Array.isArray(obj)) {
for (let i of obj) {
result.push(normalizeObject(i));
}
} else if (typeof obj == "object") {
for (let i of Object.keys(obj)) {
result.push({ name: i, value: normalizeObject(obj[i]) });
}
} else {
return obj;
}
return result;
}
console.log(JSON.stringify(normalizeObject(obj), null, 2));
This looping method called recursion. Which is loop by calling function itself.

How to check if a JSON key has unique values in a JSON file using javascript?

I have a JSON file like(for example) :
"fields": {
"asset": {
"values": [{
"asset": {
"id": "Info_text",
"type": "text",
"value": "ABCD"
}
},
{
"asset": {
"id": "Info_input",
"type": "input",
"value": "ABCDE"
}
}
]
}
}
How can I iterate over the values of "id" and check if they a unique or not in javascript?
here is complete demo without additional library, you can find if any key/value pair is unique in a json object and how many occurences were found :
var jsonData = {
"fields": [
{
"asset": {
"id": "Info_input",
"values": [
{
"asset": {
"id": "Info_text",
"type": "text",
"value": "ABCD"
}
},
{
"asset": {
"id": "Info_input",
"type": "input",
"value": "ABCDE"
}
},
{
"asset": {
"id": "Info_input",
"type": "input",
"value": "ABCDE"
}
}
]
}
}
]
}
function findKeyValueCount(key, value, obj) {
var count = 0;
var keys = Object.keys(obj);
keys.forEach(function(k) {
var v = obj[k];
if(typeof v === 'object') {
count += findKeyValueCount(key, value, v)
}
else if(k === key && v === value) {
count += 1;
}
});
return count;
}
function isUnique(key, value, obj) {
return findKeyValueCount(key, value, obj) === 1;
}
console.log(findKeyValueCount('id', 'Info_text', jsonData));
// -> 1
console.log(findKeyValueCount('id', 'Info_input', jsonData));
// -> 3
console.log(findKeyValueCount('value', 'ABCDE', jsonData));
// -> 2
console.log(findKeyValueCount('xxx', 'yyy', jsonData));
// -> 0
console.log(isUnique('id', 'Info_input', jsonData));
// -> false
console.log(isUnique('id', 'Info_text', jsonData));
// -> true
Have fun !

How to iterate nested json object?

I have a nested JSON Object and i want to iterate that.
JSON Response
{
"specifications": {
"IP6": {
"name": "Devices",
"productSubType": "Device",
"productSpecificationType": "Phones"
}
},
"offers": {
"US-PRE-IPHONE-CASE": {
"path": "productDetails/IP6",
"familyData": {
"0": "Missing Family Level data Should be here"
},
"facets": [],
"type": [],
"offers": {
"US-PRE-HG-PH-IP6": {
"hashDigest": "cf23df2207d99a74fbe169e3eba035e633b65d94",
"offerName": "offerNameString",
"productName": "iPhone 6 Case Mate Naked Tough Case - Clear",
"productOfferings": {
"ratings": "4.5",
"noOfReviews": "2010"
},
"offerStatus": {},
"displayPriority": "100200",
"descriptions": {
"shortDescription": "Iphone Decription ",
"longDescription": "longDescriptionStri6 descriptionng",
"alternativeDescription": "alternativeDescriptionString",
"reprsentativeDescription": ""
},
"specifications": [
"someSpecificationId1"
],
"brand": "Apple",
"productType": "Device",
"productSubType": "Phone",
"offerType": "",
"offerSubType": "",
"compatibility": {},
"classification": [],
"images": {
"thumbanail": {
"imagePath": "http://s.tmocache.com/images/png/products/accessories/SUPM43270/SUPM43270-small.png"
}
},
"equipmentCharacteristics": {},
"offerVariants": {},
"type": "hard-good",
"offers": [],
"family": "IP6",
"pricePoints": {
"withServicePrice16GBNEW": {
"displayPriority": "1001",
"pricingMessage": "device price with service activation",
"price": "34.99",
"discounts": {}
}
},
"dynamicPricingData": {},
"inventoryData": {
"SKUGOLD16GBN": {
"availibility": "Pre-order now!",
"availableTimeline": ""
}
}
}
}
}
}
}
Now as you see there are nested JSON objects in this and I want the value of
productName
shortDescription
imagePath
availibility
What I have tried is
function change(){
var acc = response; //response is JSON Object mentioned above
var accArray = [];
var accArray1 = [];
for (var obj in acc.specifications){
accArray.push(obj);
}
alert(accArray[0]);
for (var obj in accArray[0].offers){
accArray1.push(obj);
}
alert(accArray1[0]);
}
I am able to get the first object the first alert output is
IP6
but when I am trying to iterarte the IP6 object in same way the output is
undefined
I want to fetch all the 4 values as I mentioned above and then put them in an array.
As Grundy pointed out in his comment, obj in your code is the key of properties/items in specifications object. That means 'obj' is just a string.
To get reference to the object, change your code as below:
for(var obj in acc.specifications){
accArray.push(acc.specifications[obj]);
}
For better readability change obj to key
You can use for..in loop and recursion.
function find(obj, fieldName){
if(Array.isArray(obj)){
for(var i=0, len=obj.length;i<len;i++){
var nested = find(obj[i],fieldName);
if(nested.isFind) return nested;
}
}else{
if(typeof obj !== "object") return {isFind:false};
for(var i in obj){
if(i === fieldName) return {isFind:true, value:obj[i]};
var nested = find(obj[i],fieldName);
if(nested.isFind) return nested;
}
}
return {isFind:false};
}
this function return object with field isFind for case when available value can be null or undefined
var obj = {
"specifications": {
"IP6": {
"name": "Devices",
"productSubType": "Device",
"productSpecificationType": "Phones"
}
},
"offers": {
"US-PRE-IPHONE-CASE": {
"path": "productDetails/IP6",
"familyData": {
"0": "Missing Family Level data Should be here"
},
"facets": [],
"type": [],
"offers": {
"US-PRE-HG-PH-IP6": {
"hashDigest": "cf23df2207d99a74fbe169e3eba035e633b65d94",
"offerName": "offerNameString",
"productName": "iPhone 6 Case Mate Naked Tough Case - Clear",
"productOfferings": {
"ratings": "4.5",
"noOfReviews": "2010"
},
"offerStatus": {},
"displayPriority": "100200",
"descriptions": {
"shortDescription": "Iphone Decription ",
"longDescription": "longDescriptionStri6 descriptionng",
"alternativeDescription": "alternativeDescriptionString",
"reprsentativeDescription": ""
},
"specifications": [
"someSpecificationId1"
],
"brand": "Apple",
"productType": "Device",
"productSubType": "Phone",
"offerType": "",
"offerSubType": "",
"compatibility": {},
"classification": [],
"images": {
"thumbanail": {
"imagePath": "http://s.tmocache.com/images/png/products/accessories/SUPM43270/SUPM43270-small.png"
}
},
"equipmentCharacteristics": {},
"offerVariants": {},
"type": "hard-good",
"offers": [],
"family": "IP6",
"pricePoints": {
"withServicePrice16GBNEW": {
"displayPriority": "1001",
"pricingMessage": "device price with service activation",
"price": "34.99",
"discounts": {}
}
},
"dynamicPricingData": {},
"inventoryData": {
"SKUGOLD16GBN": {
"availibility": "Pre-order now!",
"availableTimeline": ""
}
}
}
}
}
}
}
function find(obj, fieldName){
if(Array.isArray(obj)){
for(var i=0, len=obj.length;i<len;i++){
var nested = find(obj[i],fieldName);
if(nested.isFind) return nested;
}
}else{
if(typeof obj !== "object") return {isFind:false};
for(var i in obj){
if(i === fieldName) return {isFind:true, value:obj[i]};
var nested = find(obj[i],fieldName);
if(nested.isFind) return nested;
}
}
return {isFind:false};
}
var result = ['productName','shortDescription','imagePath','availibility'].map(function(el){ return find(obj,el).value});
document.getElementById('r').innerHTML = JSON.stringify(result,null,2);
<pre id='r'></pre>
Your json code is a complex data binding structure. It same like c# complex data binding. So you need to call the obj by through it call name.
for eg:
var data = {"ex":{"a":{"a1":"a1","a2":"a2"},"b":{"b1":"b1","b2":"b2"}}}
so data is a class and it includes "ex" object
data returns =>Object {ex: Object}
if you need to access "a" or "b" object means , you need to access through the"ex" object.
for eg:
data.ex.a => Object {a1: "a1", a2: "a2"}
in your code
for(var obj in acc.specifications){
accArray.push(obj);
}
obj only push 1st element of acc.sppectification object.
So please try this.
foreach(var obj acc.specification){
arr1.push(acc.specification[obj])
}
foreach (var obj acc.offers){
arr2.push(acc.offers[obj])
}

data transformation from one form of array to another

I have doubt about data structure transformation from one form of array to another.
My input data is of the form,
var testVar=[
{
"count": 1,
"term": "Company",
"Company": [
{
"Tata": [
{
"count": 1,
"term": "Tatagroup"
}
],
"sector": "Automotive",
"type": "Car"
},
]
},
{
"count": 2,
"term": "Country",
"Country": [
{
"France": [
{
"count": 1,
"term": "France"
}
],
"region": "Europe",
"Player": "Zidane",
"term": "France",
"code": "FRA"
},
{
"region": "Europe",
"Player": "Federer",
"term": "Switzerland",
"Switzerland": [
{
"count": 1,
"term": "Switzerland"
}
],
"code": "SWI"
}
]
}];
and I am trying to transform it to the form,
[ "Tata" : [{"sector" : "automotive"}, "type" : "car"], "France": [{"region" : "Europe}, {"Player" : "Zidane"} , {"code" : "FRA"}], "switzerland" : [{"region" : "Europe}, {"Player" : "Federer"} , {"code" : "SWI"}]];
The code I came up with looks like http://jsfiddle.net/X2apw/2/, bt its nt accurate..
var testvar = [...];
var result = {};
for (var i=0; i<testvar.length; i++) {
var arr = testvar[i][testvar[i].term];
for (var j=0; j<arr.length; j++) {
var resarr = [];
for (var k in arr[j]) {
if (typeof arr[j][k] == "string") {
var obj = {};
obj[k] = arr[j][k];
resarr.push(obj);
} else {
result[k] = resarr;
}
}
}
}
(Demo at jsfiddle.net)
However, I strongly recommend to use just one object instead of an array of one-property-objects in your result format. Change the inner loop body to:
var resobj = {};
for (var k in arr[j]) {
if (typeof arr[j][k] == "string") {
resobj[k] = arr[j][k];
} else {
result[k] = resobj;
}
}
(Demo)

Categories