Restructuring JSON Response in Angular 2+ - json

I'm currently receiving a web api JSON response that is heavily nested and I want to restructure it plucking out only the data I need and making it more simple.
How would I do this in Angular 2+/Typescript?
Any help would be really appreciated.
Say I have something like this:
"O1": {
"P1": "Something",
"A1": [{
"P2": "Something",
"A2": [{
"P3": "Something"
}]
}]
"P4": "Something"
}
and I want to restructure it to this :
"O1": {
"P1": "Something",
"P2": "Something",
"P3": "Something"
}
Can I rebuild the model in a class in the constructor? If so, I haven't been able to find anything online as of yet.
Let me know if I need to provide any further info.
Thanks

Let's flatten the initial object using the snippet which was proposed. And then we can filter those properties which we need to include in the final object:
function filterObj(obj: any, propsForFilter: string[]) {
const result = {};
for (let prop in obj) {
const filteredProp = propsForFilter.find(p => prop.includes(p));
if (filteredProp) {
result[filteredProp] = obj[prop];
}
}
return result;
}
const flattened = flattenObject(obj);
console.log(flattened, filterObj(flattened, ['P1', 'P2']));
This method filterObj accepts the array of properties in order to include them in the final result. Hope this will be helpful for you.

Found this snippet in github:
https://gist.github.com/penguinboy/762197
var flattenObject = function(ob) {
var toReturn = {};
for (var i in ob) {
if (!ob.hasOwnProperty(i)) continue;
if ((typeof ob[i]) == 'object') {
var flatObject = flattenObject(ob[i]);
for (var x in flatObject) {
if (!flatObject.hasOwnProperty(x)) continue;
toReturn[i + '.' + x] = flatObject[x];
}
} else {
toReturn[i] = ob[i];
}
}
return toReturn;
}

Related

Regex for fetching JSON data

I have a JSON file abc.json
{"value1":5.0,"value2":2.5,"value3":"2019-10-24T15:26:00.000Z","modifier":[],"value4":{"value41":{"value411":5,"value412":"hey"}}}
I can get value2 using this regex
sed -E 's/."value2":"?([^,"])"?.*/\1/' abc.json
I want to know how I can get values of value411 and value412
I don't want to use jq or any other tool as my requirement is to use regex for this.
You should always try to use an existing parser, depending on what platform you work on there should be one that can interpret the data model for you.
I refer to this famous answer about parsing HTML with regex
var jData = {
"value1": 5.0,
"value2": 2.5,
"value3": "2019-10-24T15:26:00.000Z",
"modifier": [],
"value4": {
"value41": {
"value411": 5,
"value412": "hey"
}
}
};
If You try with regex then use this:
JSON.stringify(jData).match(/(?<=(\"(value411|value412)\"\:))[\"\w+]+/g)
// Output: ['5', '"hey"']
Demo: https://regex101.com/r/c3K4cH/1
Limitation: You have to put only the key name, don't try to fetch the full object
You create a javascript function get any non-empty value from a JSON, as follows:
function getData(obj, fKey, fData = null) {
for (const prop of Object.getOwnPropertyNames(obj)) {
if (!fData) {
if (typeof obj[prop] === 'object' && Object.keys(obj[prop]).length > 0 && prop !== fKey) {
return getData(obj[prop], fKey, fData)
} else {
if(prop === fKey) {
fData = obj[prop];
return fData
}
}
} else {
return fData;
}
}
}
console.log(getData(jData, 'value411'));
console.log(getData(jData, 'value412'));

Unable to parse JSON data due to errors or undefined data

I apologize if this seems similar to other questions asked but I have not been able to find any posts that have resolved this issue for me. Basically, I am getting a JSON object and I am trying to parse it but I can't parse it correctly. Mainly the WordDetails section that I am getting from a Word API. I am able to get everything outside the results section under WordDetails. Basically, when I get to results, I am not able to parse it correctly. Below is an example of the format.
{
"LastIndex": 133,
"SRDWords": [
{
"Domain": {
"URL": "abactinal.com",
"Available": true
},
"WordDetails": "{\"word\":\"abactinal\",\"results\":[{\"definition\":\"(of radiate animals) located on the surface or end opposite to that on which the mouth is situated\",\"partOfSpeech\":null,\"antonyms\":[\"actinal\"]}],\"syllables\":{\"count\":4,\"list\":[\"ab\",\"ac\",\"ti\",\"nal\"]}}"
},
{
"Domain": {
"URL": "aaronical.com",
"Available": true
},
"WordDetails": "{\"word\":\"aaronical\",\"syllables\":{\"count\":4,\"list\":[\"aa\",\"ron\",\"i\",\"cal\"]},\"pronunciation\":{\"all\":\"ɜ'rɑnɪkəl\"}}"
},
...
Here is my code below. Basically, I am getting to the results section of WordDetails but if I try to parse the results section it fails and if I try object.entries on it, it will not return a response according to the alert messages I used. I know there must be a better way but not sure what. Most articles say just JSON.parse then map it but that does not work. Any help would be appreciated!
data.Words.map(word => {
//get data
for (let [key, value] of Object.entries(word)) {
if (key === "Domain") {
url = value.URL;
availability = value.Available;
} else if (key.trim() === "WordDetails") {
alert("value " + value);
wDetails = JSON.parse(value);
for (let [key2, value2] of Object.entries(wDetails)) {
if (key2 === "word") {
//store word
} else if (key2.toString().trim() === "results") {
let test = JSON.parse(value2);
test = Object.entries(value2);
test.map(t => {
alert(t.definition);
});
}
}
}
}
});
You did JSON.parse above, no need to parse value2 again.
And value for results is an array, so no need for Object.entries.
...
} else if (key2.toString().trim() === 'results') {
let test = JSON.parse(value2); // this should be remove
test = Object.entries(value2); // this should be remove, value2 should be an array
// map value2 directly
value2.map(t => {
alert(t.definition);
});
}
...

Flutter get Object property Name

I passed the following object:
var myVar = { typeA: { option1: "one", option2: "two" } }
I want to be able to pull out the key typeA from the above structure.
This value can change each time so next time it could be typeB.
So I would like to know if there is any way to do that
I was able to solve using 'keys'
for a json example like this:
{
"1-0001": {
"name": "red",
"hex": "FF0000"
},
"1-0002": {
"name": "blue",
"hex": "0000FF"
},
"1-0003": {
"name": "green",
"hex": "008000"
}
}
I was able to use
Map<String, dynamic> decoded = json.decode(jsonString);
for (var colour in decoded.keys) {
print(colour); // prints 1-0001
print(decoded[colour]['name']); // prints red
print(decoded[colour]['hex']); // prints FF0000
}
To get all filenames you can use:
var data = ...
var filenames = [];
for(var i = 0; i < data.length; i++) {
var item = data[0]['files'];
var key = item.keys.first;
var filename = item[key]['filename'];
filenames.add(filename);
}
print(filenames);
You need to define a data type.
It is basically a map of (key value-pair) where key is changed as stated in question typeA or typeB
This Object has 2 properties option1 and option2 which is also strings.
Here is the sample code to construct model and how to use it
import 'package:TestDart/TestDart.dart' as TestDart;
main(List<String> arguments) {
var map = new Map<String, MyObject>();
map['typeA'] = new MyObject("one", "two");
map['typeB'] = new MyObject("one", "two");
print(map['typeA'].toString());
print(map['typeA'].toString());
}
class MyObject {
String _option1;
String _option2;
MyObject(this._option1, this._option2);
String get option2 => _option2;
String get option1 => _option1;
#override
String toString() {
return 'MyObject{option1: $_option1, option2: $_option2}';
}
}
Relevant answer
map.forEach((key, value) {
print("Key : ${key} value ${value}");
});

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);

Loop to add data to complex JSON object

I have a complex JSON Object like this:
var requestData = { __batchRequests: [ { __changeRequests: [
{ requestUri: "Customers", method: "POST", headers: { "Content-ID": "1" }, data: {
CustomerID: 400, CustomerName: "John"
} }
] } ] };
I am trying to do two things:
Declare this object but with the variable data empty
With a loop, add items dynamically to the data object,
How can I do it?
This isn't too complex an object. And it isn't JSON until it's converted into a string.
Right now, it's just plain-ol' JS objects and arrays.
Breaking that down into its elements might look like this:
var requestData = {};
requestData.__batchRequests = [];
requestData.__batchRequests[0] = {};
requestData.__batchRequests[0].__changeRequests = [];
requestData.__batchRequests[0].__changeRequests[0] = {};
requestData.__batchRequests[0].__changeRequests[0].requestUri = "Customers";
requestData.__batchRequests[0].__changeRequests[0].method = "POST";
requestData.__batchRequests[0].__changeRequests[0].headers = { "Content-ID" : "1" };
requestData.__batchRequests[0].__changeRequests[0].data = {};
Aside from the repeats, what do you see?
Personally, I see that __changeRequests[0] is an object as simple as:
var changeRequest = {
requestUri : "Customers",
method : "POST",
headers : { "Content-ID" : "1" },
data : {}
};
I also see that I can just push that onto my array of change requests:
requestData.__batchRequests[0].__changeRequests.push(changeRequest);
Right?
I also know that my changeRequest variable still points to the one that I just added to the array, and whatever I change on the object will show up as changed in the array's reference to the object, too:
changeRequest.data.CustomerName = "Bob";
changeRequest.data.CustomerID = "204";
requestData.__/*...*/changeRequests[0].data.CustomerName; // Bob
So how about writing yourself some helper-functions?
function extend (obj, additions) {
var key;
for (key in obj) { if (additions.hasOwnProperty(key)) {
obj[key] = additions[key];
}
}
function makeChangeRequest (url, method, headers, data) {
var request = {
requestUri : url,
method : method,
headers : {},
data : {}
};
extend(request.headers, headers);
extend(request.data, data);
return request;
}
function getBatch (num) { return requestData.__batchRequests[num]; }
var changeReq = makeChangeRequest("Customers",
"POST",
{ "Content-ID" : "1" },
{ CustomerName : "Bob", CustomerID : "2012" });
var batch = getBatch(0);
batch.__changeRequests.push(changeReq);
If you want to add more data to changeReq.data later:
extend(changeReq.data, { Address : "33 Nowhere Rd.", City : "Splitsville" });
For the first part of your question, you can initialize data with an empty associative array:
var requestData = { __batchRequests: [ { __changeRequests: [
{ requestUri: "Customers", method: "POST", headers: { "Content-ID": "1" }, data: {} }
] } ] };
This next part assumes, perhaps incorrectly, that you can use jQuery. It also assumes that you have an array containing all of the relevant key value pairs.
var customerDeetsArray =[{CustomerID: 400}, {CustomerName: "John"}];
for (var i in customerDeetsArray) {
requestData.data = $.extend(requestData.data, customerDeetsArray[i]);
}
See working example which makes use of console.debug:
http://jsfiddle.net/4Rh72/6/