Parsing a dynamic JSON object - javascript

I am working on parsing a JSON and searching for specific key in that JSON object. The problem is that the structure of JSON keeps changing and i cannot hard code the path, is there any better ways to parse?
or
can i get this to convert in to regular JSON key value pairs as below
{
"resourceName": "Bundle",
"id": "6d6e-81d5-5a1e2b452563",
"lastUpdated": "2069-06-21",
"url": "http://abcd.com",
.
.
.
... so on
}
I have tried using hard coded methods but that doesnt seem to work always
Here is snipped of JSON
{
"resourceName": "Bundle",
"id": "6d6e-81d5-5a1e2b452563",
"meta": {
"lastUpdated": "2069-06-21"
},
"data1": [{
"url": "http://abcd.com",
"value": {
"url": "http://abcd.com",
"value": [{
"url": "Severity",
"value": "info"
}, {
"url": "dfew",
"value": "fefdd"
}, {
"url": "fwef",
"value": "This is data blah blah"
}]
}
}]
}

You search the object recursively:
function get_lastUpdated(obj)
{
for ( var key in obj )
{
if ( key == "lastUpdated" ) return obj[key];
if ( typeof obj[key] == "object" )
{
var res = get_lastUpdated(obj[key]);
if ( res ) return res;
}
}
return null;
}
For a simple case, something like above could work.

When you call JSON.parse, you can pass in a callback function, called a reviver, which will be recursively applied to all key-value pairs. For example:
var jsonString = `{
"resourceName": "Bundle",
"id": "6d6e-81d5-5a1e2b452563",
"meta": {
"lastUpdated": "2069-06-21"
},
"data1": [{
"url": "http://abcd.com",
"value": {
"url": "http://abcd.com",
"value": [{
"url": "Severity",
"value": "info"
}, {
"url": "dfew",
"value": "fefdd"
}, {
"url": "fwef",
"value": "This is data blah blah"
}]
}
}]
}`;
var obj = {};
JSON.parse(jsonString, (key, value) => {
if (typeof value === "string" && !(key in obj)) {
obj[key] = value;
}
});
console.log(obj);
If have already parsed the object, you can use a similar strategy with JSON.stringify and the replacer callback:
var data = {
"resourceName": "Bundle",
"id": "6d6e-81d5-5a1e2b452563",
"meta": {
"lastUpdated": "2069-06-21"
},
"data1": [{
"url": "http://abcd.com",
"value": {
"url": "http://abcd.com",
"value": [{
"url": "Severity",
"value": "info"
}, {
"url": "dfew",
"value": "fefdd"
}, {
"url": "fwef",
"value": "This is data blah blah"
}]
}
}]
};
var obj = {};
JSON.stringify(data, (key, value) => {
if (typeof value === "string" && !(key in obj)) {
obj[key] = value;
}
return value;
});
console.log(obj);

Related

why arrow function return undefined

I'm writing a function that simply loops through a Json schema. Let us say we have a simple json schema such as:
var foo = {
"description": "A car schema",
"type": "object",
"properties": {
"_id": {
"type": "string"
},
"_rev": {
"type": "string"
},
"sources": {
"type": "object",
"properties": {
"mam": {
"type": "object",
"properties": {
"source_id": {
"type": [ "integer", "null" ]
},
"SOR": {
"type": ["boolean","null"]
}
}
},
"sas": {
"type": "object",
"properties": {
"source_id": {
"type": "string"
},
"SOR": {
"type": ["boolean","null"]
},
"CAR": {
"type": ["object","null"]
}
}
}
}
}
}
}
We're trying to collect the type of the key object from it. Here is function search for CAR type should return => "object"
parseObjectProperties = (obj)=> {
for (var k in obj) {
if(k === "CAR"){
console.log(_.values(obj[k])[0][0]) // When I do a console log like this prin the object value
return _.values(obj[k])[0][0] // but in return i get undefined
}
if ( _.isObject( obj[k]) && !_.isNil(obj[k])) {
return parseObjectProperties(obj[k])
}
}
}
parseObjectProperties(foo);
When I run it, the inner console.log(_.values(obj[k])[0][0]) shows the correct value: object
but if i run it
console.log(parseObjectProperties(foo));
I get
undefined
Why isn't the function properly returning the correct value => "object"?
Thank you!
I just re-wrote this as I didn't understand the logic you were using. Does this solve your problem?
FYI your object CAR, has a property named type whose value is an array that contains 2 values, "object" and "null" so you want to use obj[k].type[0] if you want to get "object" as the result.
const parseObjectProperties = (obj) => {
var result = null;
for (var k in obj)
if (k == "CAR") return obj[k].type[0];
else if (obj[k] instanceof Object)
result = parseObjectProperties(obj[k]);
return result;
}
var foo = {
"description": "A car schema",
"type": "object",
"properties": {
"_id": {
"type": "string"
},
"_rev": {
"type": "string"
},
"sources": {
"type": "object",
"properties": {
"mam": {
"type": "object",
"properties": {
"source_id": {
"type": ["integer", "null"]
},
"SOR": {
"type": ["boolean", "null"]
}
}
},
"sas": {
"type": "object",
"properties": {
"source_id": {
"type": "string"
},
"SOR": {
"type": ["boolean", "null"]
},
"CAR": {
"type": ["object", "null"]
}
}
}
}
}
}
}
console.log(parseObjectProperties(foo));

write a recursive function to format the object in javascript

I have a JSON object as follows,
x = {
"prop1": {
"description": "prop1",
"dataType": "string",
"value" : "abc"
},
"prop2": {
"sub1": {
"description": "sub1",
"dataType": "integer",
"value" : 12
},
"sub2": {
"description": "sub2",
"dataType": "integer",
"value" : 15
}
},
"prop3": {
"input": {
"name": {
"description": "Whether to validate input messages",
"dataType": "boolean",
"value": false
}
},
"output": {
"description": "Whether to validate output messages",
"dataType": "boolean",
"value": false
}
}
}
I need to convert this object as below.
y = {
"prop1": "abc",
"prop2.sub1" :12,
"prop2.sub2" : 15,
"prop3.input.name" : false,
"prop3.output" : false,
}
I have to create the key name with "." in between prop and sub prop. need to write a recursive function. Any ideas on how to write the recursive function for this?
my code for this.
propPrefix = '';
y = {};
function createObject(props){
Object.keys(props).forEach(prop => {
const obj = props[prop];
const hasChildObject = Object.keys(obj).find(key => typeof(obj[key]) == 'object');
if(hasChildObject){
propPrefix = propPrefix == "" ? prop + '.' : (propPrefix + '.' + prop);
createObject(obj);
}else{
const value = obj.value;
y[propPrefix + prop] = value;
}
})
}
Here is a recursive solution for your problem. I go through each key of the object in each function call and stop if I find a key named value, store it in the obj1 variable
x = {
"prop1": {
"description": "prop1",
"dataType": "string",
"value" : "abc"
},
"prop2": {
"sub1": {
"description": "sub1",
"dataType": "integer",
"value" : 12
},
"sub2": {
"description": "sub2",
"dataType": "integer",
"value" : 15
}
},
"prop3": {
"input": {
"name": {
"description": "Whether to validate input messages",
"dataType": "boolean",
"value": false
}
},
"output": {
"description": "Whether to validate output messages",
"dataType": "boolean",
"value": false
}
}
}
function findValue(obj, string, obj1) {
if (obj.hasOwnProperty("value")) {
obj1[string.substring(1)] = obj.value
return
}
for (var key in obj) {
findValue(obj[key], [string, key].join("."), obj1)
}
}
var y = {}
findValue(x, "", y)
console.log(y)
Result is of the desired format
{ prop1: 'abc',
'prop2.sub1': 12,
'prop2.sub2': 15,
'prop3.input.name': false,
'prop3.output': false }

Reformat Existing JSON into new JSON using Javascript/Typescript

I currently have an existing JSON that I want to change/reformat into a new JSON to be able to be used in an external service. The format is a bit complicated but I can't change it, so I have to edit my existing JSON. to match my desired output.
Existing JSON:
{
"specifiers": [{
"value": "test",
"type": "text",
"label": "Brand ID"
}, {
"value": "test",
"type": "text",
"label": "Program ID"
}]
}
Desired Output:
{
"specifiers": {
"Brand ID": {
"text": {
"value": "test",
"type": "text"
}
},
"Program ID": {
"text": {
"value": "test",
"type": "text"
}
}
}
}
I've tried iterating through the existing JSON using loops, but I don't really know how to format my loops to use the values as the keys? I'm guessing that I might have to use Object.keys or Object.values, but I'm not sure how to get a specific value for a specific key.
Example Format:
"[label]": {
"[type]": {
"value": [value],
"type": [type]
}
}
function tranform({specifiers}) {
return { specifiers: specifiers.reduce((obj, {label, type, value}) => ({...obj, [label]: { [type]: { type, value } } }), {}) }
}
const json = {
"specifiers": [{
"value": "test",
"type": "text",
"label": "Brand ID"
}, {
"value": "test",
"type": "text",
"label": "Program ID"
}]
}
console.log(tranform(json))
Pretty straightforward with a reduce:
const formattedSpecifiers = existingJSON.specifiers.reduce((newSpecifiers, specifier) => {
newSpecifiers[specifier.label] = {
[specifier.type]: {
type: specifier.type,
value: specifier.value,
},
};
};
return newSpecifiers;
}, {});
const newJSON = { specifiers: formattedSpecifiers };
you can use #Array.reduce. snippet below.
let input = {
"specifiers": [{
"value": "test",
"type": "text",
"label": "Brand ID"
}, {
"value": "test",
"type": "text",
"label": "Program ID"
}]
}
const res = input.specifiers.reduce((res, obj) => {
const {
label,
type,
value
} = obj
res[label] = {};
res[label][type] = {
value,
type
};
return res;
}, {});
console.log(res);

how to navigate through complex JSON dynamically in JavaScript

I'm trying to navigate through a complex nested JSON, however my attempt didn't get me too far as it keeps returning me the last index JSON.
This is how my Objects looks like, and trying to navigate through it and getting other objs/schemas that are in $ref.
Raw JSON
{
"type": "object",
"properties": {
"Id": {
"format": "int32",
"type": "integer"
},
"Status": {
"enum": [
"Preparing",
"AwaitingCompletion",
"Cancelled",
"Completed"
],
"type": "string"
},
"ExternalReference": {
"type": "string"
},
"Customer": {
"$ref": "#/definitions/Customer"
},
"OrderLineGroups": {
"type": "array",
"items": {
"$ref": "#/definitions/OrderLineGroup"
}
},
"Promotions": {
"type": "array",
"items": {
"$ref": "#/definitions/PromotionSummary"
}
},
"OriginatingSite": {
"type": "object",
"properties": {
"Id": {
"format": "int32",
"type": "integer"
},
"PropertyCode": {
"type": "string"
},
"StoreCode": {
"type": "string"
}
}
},
"CustomData": {
"type": "object",
"additionalProperties": {
"type": "array",
"items": {
"type": "object"
}
}
}
}
}
In my code I have done for() and hasOwnProperty(), however my problem is that it doesn't give me all the JSON back even the condition is met (e.g if there's no type property), it only gives the last index or object that doesn't have type property. Also doesn't return me any of the objects if type property is array.
// Get property of #/definitions/obj
let prop = apiDefinition[splitResponse.split('/')[2]].properties;
console.log([prop])
var s = [apiDefinition[splitResponse.split('/')[2]].properties];
// Transform JS Object of #/definitions/Obj to JSON
var parentJSON = JSON.stringify(apiDefinition[splitResponse.split('/')[2]]);
for (var x in prop) {
if (prop.hasOwnProperty(x)) {
if (prop[x].type && prop[x].type === 'array') {
console.log('All type Array >> ', x);
let objKeyProp = apiDefinition[prop[x].items.$ref.split('/')[2]];
let objJsonStringified = JSON.stringify(objKeyProp);
let refString = '{"$ref"'+':' + '"' + prop[x].items.$ref + '"}';
this.compiledJson = JSON.parse(parentJSON.replace(refString, objJsonStringified));
} else if (!prop[x].type) {
console.log('all arrays >> ', x)
let objKeyProp = apiDefinition[prop[x].$ref.split('/')[2]];
let objJsonStringified = JSON.stringify(objKeyProp);
let refString = '{"$ref"'+':' + '"' + prop[x].$ref + '"}';
this.compiledJson = JSON.parse(parentJSON.replace(refString, objJsonStringified));
}
}
}

Converting a json schema to angular-tree-control treemodel

I have a very large json schema which I would like to display in an Angular Tree Control. However, the json schema is not exactly in the treemodel format supported by the Angular Tree Control. For example, the children (properties) in the schema are not in an array. How would I go about converting the json schema into a treemodel format?
The schema looks something like this (except more complicated with up to 10 levels of nesting):
{
"type": "object",
"properties": {
"firstName": {
"type": "string"
},
"lastName": {
"type": "string"
},
"address": {
"type": "object",
"properties": {
"addressLine1": {
"type": "string"
},
"addressLine2": {
"type": "string"
}
}
}
}
}
For it to render correctly in the Angular Tree Control, it needs to look like this:
{
"type": "object",
"properties": [
{
"name": "firstName",
"type": "string"
},
{
"name": "lastName",
"type": "string"
},
{
"name": "address",
"type": "object",
"properties": [
{
"name": "addressLine1",
"type": "string"
},
{
"name": "addressLine2",
"type": "string"
}
]
}
]
}
This is an example, can be refactored to be recursive to deeper levels.
var data = {
"type": "object",
"properties": {
"firstName": {
"type": "string"
},
"lastName": {
"type": "string"
},
"address": {
"type": "object",
"properties": {
"addressLine1": {
"type": "string"
},
"addressLine2": {
"type": "string"
}
}
}
}
};
function toTreeModel(obj){
var treeModel = {};
for (var a in obj) {
if(a === 'properties'){
treeModel[a] = []
var i = 0;
var e = 0;
for(b in obj[a]){
if(obj[a][b].type === 'object'){
treeModel[a][i] = {name: b, type: obj[a][b].type, properties: []};
for(c in obj[a][b].properties){
treeModel[a][i].properties.push({name: c, type: obj[a][b].properties[c].type});
e++;
}
} else {
treeModel[a][i] = {name: b, type: obj[a][b].type};
}
i++;
}
} else {
treeModel[a] = obj[a];
}
}
return treeModel;
}
var toTree = toTreeModel(data);
// console.log(toTree);
document.getElementById("output").innerHTML = JSON.stringify(toTree, undefined, 2);
<pre id="output">
</pre>
it support nested also
var data = {
"type": "object",
"properties": {
"checked": {
"type": "boolean",
},
"dimensions": {
"type": "object",
"properties": {
"width": {
"type": "integer",
},
"height": {
"type": "integer",
},
"volume": {
"type": "object",
"properties": {
"length": {
"type":"integer",
},
"breadth":{
"type": "integer"
}
}
}
}
},
"id": {
"type": "integer",
},
"name": {
"type": "string",
},
"price": {
"type": "number",
}
}
}
function findProperties(obj){
let properties = []
for(key in obj){
if(obj[key].properties){
properties.push({name: key, datatype: obj[key].type, properties: findProperties(obj[key].properties)})
}else{
properties.push({ name: key, datatype: obj[key].type});
}
}
return properties;
}
function findData(data){
let result = "";
for(key in data){
if(key == 'properties'){
result = findProperties(data.properties)
}
}
return result;
}
console.log(JSON.stringify(findData(data)));

Categories