ionic 2 get data from malformed json - javascript

is there anyway i can get this malformed json format which is odd i have no control over this json manually so i need to get this data and manipulate it with rxjs observable from http get
{
"firstNm": "Ronald",
"lastNm": "Mandez",
"avatarImage": "https://randomuser.me/api/portraits/men/74.jpg"
}
{
"firstNm": "Ronald",
"lastNm": "Mandez",
"avatarImage": "https://randomuser.me/api/portraits/men/74.jpg"
{
"firstNm": "Ronald",
"lastNm": "Mandez",
"avatarImage": "https://randomuser.me/api/portraits/men/74.jpg"
}

I tried with your JSON in the console and this seems to work. In the map function I've used you can probably implement more generic replacement methods to alter the strings, but it works for this example.
function fixBadJSON(response){
let badJSON = JSON.stringify(response); // added this edit in case you don't know how to get the response to a string
let arr = badJSON.split('}\n'); // Looks like the JSON elements are split by linefeeds preceded by closing bracket, make into arr length of 3
let fixedArr = arr.map((item)=>{ // map the array to another, replace the comma at the end of the avatarImage key. elements in array should be proper JSON
if(item[item.length] != '}') item += '}'; //put the brackets back at thend of the string if they got taken out in the split, probably a better way to handle this logic with regex etc
return item.replace('jpg",','jpg"')
});
let parsedJSON = JSON.parse(JSON.stringify(fixedArr));
return parsedJSON
}
Take the JSON data you've posted up there and copy it to a variable as a string and test the function, it will return a properly formatted array of JSON data.
Call that when you get a response from your service to transform the data. As far as the observable chains and any async issues you might be seeing those are separate things. This function is just designed to convert your malformed JSON.

Related

looking for a regex pattern to remove contents in a JSON string

I have a JSON string something similar to:
string str=[
{"name": "Dukes",
"lastname":"Chavez",
"salary":"10000",
"clearingbankAccinfo":"Westpac"}]
The issue is we have to clear the bank info, and that can be any value.
What we know for sure is it would come at the end of the string.
I need a regex pattern to remove this clearingbankAccInfo so that it looks something similar to:
string str=[
{"name": "Dukes",
"lastname":"Chavez",
"salary":"10000"}]
Unfortunately I would have not accepted this as input itself but this information comes from a diff process and I have no control over what they pass.
I have tried:
String str=str.replace(',"clearingbankAccInfo":\g[a-zA-Z0-9_:]\g+', '' )
But it doesn't work correctly
If you're working with something like JSON regex is the wrong solution. Simply parse the stringified data, and loop over it with something like map to extract and return the correct data. Then you can just make a string again out of that data.
const str = '[{"name": "Dukes","lastname": "Chavez","salary": "10000","clearingbankAccinfo": "Westpac"},{"name": "Bob","lastname": "Smith","salary": "20000","clearingbankAccinfo":"Lloyds"}]';
// Here we're creating a new variable called `newData` to hold
// the transformed data. We parse the data string and iterate over it
// (because it's now an array) with `map` which is an array method.
// With each iteration we take the object, grab the clearingBankAccinfo
// and just return everything else.
const newData = JSON.parse(str).map(obj => {
const { clearingbankAccinfo, ...rest } = obj;
return rest;
});
console.log(newData);
console.log(JSON.stringify(newData));
Additional documentation
Rest parameters
Working with JSON
Destructuring assignment
str=str.replace(/,?"clearingbankAccinfo":"\w+"/g, '');

When I make a POST request to my back-end and try to access the body, every property is converted to string, including arrays

I just realized that when I make a POST request like this:
async createProduct(){
let formData = new FormData();
formData.append("name", "test")
formData.append("price", 150)
formData.append("brands", [1, 2])
let response = await axios.post("/createProduct", formData)
}
And then console.log() the typeof each property on the back-end, I always get a string:
console.log(typeof req.body.brands) --> String 1, 2
console.log(typeof req.body.price) --> String 150
Why is this happening and how can I turn them to their original data types? I guess I can turn the req.body.price to integer with parseInt(), but how to turn req.body.brands back to an array?
I'm assuming you're using something like multer as a body parser to handle form-data.
You are adding the array wrong. The formData.append() function only accepts a string as argument. This causes [1,2] to be converted to a string automatically which conveniently is equal to [1,2].join(', ').
However, form-data does indeed support multiple values which multer will parse into arrays. But note that it support multiple values. Not arrays. So the correct syntax to add an array of values is:
formData.append("brands", 1);
formData.append("brands", 2);
Or more generally:
[1,2].forEach(x => formData.append("brands", x));
Doing this your backend should correctly parse the values into an array:
console.log(typeof req.body.brands) --> Array [1,2]
Your question is very confusing. How do you console.log() on the back-end?
If you meant, front-end and you are using PHP or whatever, if you receive an object response, you still have to convert it to your desired data type.
For JSON
var a = JSON.parse(response)
Then if you're expecting an array,
you should make the response an array type in the server. That way, Javascript will automatically detect it as an array.
console.log(response.length)
If you want convert your data to array in the server:
$data = array(1,2,3);
Then ensure you use a proper encoding type to flush response back to the HTML page.
echo json_encode($data);
If you already have your data and want to convert it to an array, do this:
var arr = [];
var data = response.split(',');
//Loop through data
for(var x=0;x < data.length;x++) {
arr.push(data[x]);
}
console.log(typeof arr) //Array (Object)```
Ordinarily, The ```arr = arr.split(',');```
is already an array and can be worked on

Dirty JSON objects not in array - how can I parse this?

I'm currently trying to parse the following JSON output.
These JSON objects are stored in one big string and not in a JSON array. As such it is not valid JSON.
{"output": "te\ns\nt"}
{"output": "test"}
This string also contains multiple new lines. So splitting on new lines is not an option.
Nevertheless is there any way of parsing this invalid JSON that it results in a valid array of JSON objects?
If your object-list (let's call it that) contains valid objects you can first make an array from each line and then go through that array and parse the JSON:
let data = `{"output": "test"}
{"output": "test"}`; //template string to make the newlines work flawless...
// first split on newline filter out "" map to the parsed JSON
data = data.replace(/}\n*/g, "}**").split("**") .filter(Boolean) .map(JSON.parse);
console.log(data);
Here's something dirty that might work.
let string = `{"output": "te\ns\nt"}
{"output": "test"}`
let json = JSON.parse(`[${string.replace(/}[\s]*\{/g, '}, {').replace(/\n/g, '\\n')}]`)
console.log(json) // [ { output: 'te\ns\nt' }, { output: 'test' } ]
Not pretty and quite fragile, but quick.

parsing json data without a comma separator

My JSON is like below
{"_id":707860,"name":"Hurzuf","country":"UA","coord":{"lon":34.283333,"lat":44.549999}}
{"_id":519188,"name":"Novinki","country":"RU","coord":{"lon":37.666668,"lat":55.683334}}
{"_id":1283378,"name":"Gorkhā","country":"NP","coord":{"lon":84.633331,"lat":28}}
{"_id":1270260,"name":"State of Haryāna","country":"IN","coord":{"lon":76,"lat":29}}
{"_id":708546,"name":"Holubynka","country":"UA","coord":{"lon":33.900002,"lat":44.599998}}
It is a JSON without comma separation, how to read this file? I tried to parse the JSON and add commas in between, but couldn't do that either.
myapp.controller('Ctrl', ['$scope', '$http', function($scope, $http) {
$http.get('todos.json').success(function(data) {
var nuarr = data.toString().split("\n");
for(i in nuarr) {
myjson.push(i+",");
}
});
}]);
This format is typically called "newline-delimited JSON" or "ndjson"; there are several modules that can parse this, but if you're data set is small and you can do it all at once, you're on the right track:
var ndjson = "..." // assuming your data is already loaded in as a string
var records = ndjson.split('\n').map(function (record) {
return JSON.parse(record)
})
That simplifies it a bit, but then you have all of your records in an array, as parsed JSON objects. What you do to them after that is up to you, but the key takeaway here is that your JSON is a list of objects, not a single object: you don't want to parse it as a whole, but as individual records.
Say then, you want to create an object whose keys are the individual IDs; that might be helpful:
var recordHash = {}
records.forEach(function (record) {
recordHash[record._id] = record
})
Now you can address the individual records as recordHash['12345678'] assuming that 12345678 is the id of the record you wanted. You'll want to mutate the records into whatever data structure makes sense for your application, so it really depends on what you're looking for, but that example might get you started.
I really don't recommend trying to mutate the data that you're receiving into some other format before parsing; it's fragile. You'll find it much safer and more re-usable to parse out the data in the way you were provided it, and then transform it into whatever data structure makes sense for your application.
$http.get expects that response must be json. You can write your own custom response transformer to do that so.
$http({
url: 'todos.json',
method: 'GET',
transformResponse: function (data) {
return data.split('\n').map(function(line) {
return JSON.parse(line);
});
}
}).success(function (response) {
console.log(response);
// do whatever you want to do
// response will be of type array of objects
});
Your JSON needs to be a single object or array. Just joining a bunch of objects together with a comma does not define a single JSON object. Try this instead to get a parsable array of objects:
var nuarr = data.toString().split("\n");
myjson = '[' + nuarr.join(',') + ']';
Then JSON.parse(myjson) should return an array of objects. Alternatively, you can just map each element of nuarr to it's JSON-parsed value and collect the results in another array.
$http.get expects that response must be json. You can write your own custom response transformer to do that so.
$http({
url: 'todos.json',
method: 'GET',
transformResponse: function (data) {
return data.split('\n').map(function(line) {
return JSON.parse(line);
});
}
}).success(function (response) {
console.log(response);
// do whatever you want to do
// response will be of type array of objects
});
var myJson = nuarr.join(',');
But what are you really trying to do? Your code is pushing the strings with a comma added into an array, so end up with
["{...},", "{...},", ...]
As I see it, You have a collection of json objects, with the delimiter as newline.
Try this:
myapp.controller('Ctrl', ['$scope', '$http', function($scope, $http) {
$http.get('todos.json').success(function(data) {
myjson = data.split("\n").map(function(line) { return JSON.parse(line); });
});
}]);
Use a regexp to split into lines, then map each line into its JSON-parsed equivalent, yielding an array of the objects on each line:
input . match(/^.*$/gm) . map(JSON.parse)
Or use split as other answers suggest:
input . split('\n') . map(JSON.parse)
As stupid as it may seem, we got tired of using commas and quotes with JSON, along with not having comments or multiline strings.
Knowing that Douglas Crockford and his disciples would cry 'Blasphemy', we proceeded to write a specification, parser, and formatter for our own Relaxed Json syntax.
The fact is you don't really need commas, and quotes are only needed in a few exceptional cases. And you don't need newlines either.
With Relaxed Json, to make your example work, you would just put '[' and ']' around what you already have and call
val realJson = parser.stringToJson(...)
But you don't need newlines between the array values.
And you can also remove all the commas in-between your key-values.
And you don't need quotes around your keys.
So you could do this:
[
{ _id:707860 name:Hurzuf country:UA
coord:{lon:34.283333 lat:44.549999}
}
{ _id:519188 name:Novinki country:RU
coord:{lon:37.666668 lat:55.683334}
}
]
Link To Specification:
http://www.relaxedjson.org
Link To NPM
https://www.npmjs.com/package/really-relaxed-json
Paste the example here to see how easy it is to parse:
http://www.relaxedjson.org/docs/converter.html
Update 2022
#milkandtang answer put me on the right path but JSON.parse() gave me trouble and returned errors even after splitting the lines. It keeps complaining about lines being empty or malformated.
This is what works for me with New-Line Delimited JSON
var ndjson = data;//must be a string
//declare variable that will be array of json
var json = [];
//split
ndjson.split('\n').map(function (record) {
//regex to format each array to a json object
var array = JSON.parse(`[${record.replace(/\}\n\{/g, '},{')}]`);
//push to json array
json.push(array);
})
//pheeew...
console.log(json);

JSON Data format

Not very familiar with JSON data and how to create it using JavaScript.this is what i am trying
i have created two JS variables
var json={};
var json1={};
i have some certain loops to iterate data and loops like
for(firstLoop){
key=outerKey;
for(innerLook){
innerKey=innerkey;
for(lastloop){
jsonValues= create values in a java variable
}
json[innerKey]=jsonValues;
}
json1[outerKey]=JSON.stringify(json);
}
Doing this i am getting following output
Required: "{"Center":"radio_Required_Center_0,radio_Required_Center_1,","Left":"radio_Required_Left_0,"}"
which is not a valid JSON format.My idea id to create a outer-key say Required and than an inner one's in my case Center and Left
so that i can iterate each value with respect to key Center (i can break the string based on ')
i am not sure how to create correct structure and i don't want to do it on server side which can be done easily.
any solution or hint will really be helpful.
Edit
var data= JSON.stringify(json1);
giving following output
{"Required":"{\"Center\":\"radio_Required_Center_0,radio_Required_Center_1,\",\"Left\":\"radio_Required_Left_0,\"}"}
which is valid JSON data, now i need to execute some code based on the data in the JSON and here are my requirements
Fetch the outer-key (Required or there can be other also).
Fetch all values under the key Center and Left
Create array from the value retrieved from step 2 (split based on ",").
Loop through the values obtained from step 3 and execute the logic.
My real challenge is at step number 2 and 3 where i need to fetch the keys and its associated values and those key and not predefined so i can not access them based on there name.
I am thinking of a way to get key and its values without hard coding key names and execute my logic.
is it possible in by this approach or not?
If you're using a modern version of Javascript, it comes with JSON functions built-in.
var jsonString = JSON.stringify(jsobject);
...to convert a JS object into a JSON string.
(See https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/JSON/stringify)
and
var jsOject = JSON.parse(jsomString);
...to convert back in the other direction.
(see https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/JSON/parse)
The only time you need to worry about this not being built-in is if you're using an old browser - for example, older versions of IE. However, in this case, there are polyfill libraries like this one that you can load which will implement the above syntax for you.
If you're just trying to compose one big JSON object, you don't need to stringify one JSON object before adding it to another... So instead of doing JSON.stringify(json) you can just do json1[outerKey]=json
for(firstLoop){
key=outerKey;
for(innerLook){
innerKey=innerkey;
for(lastloop){
jsonValues= create values in a java variable
}
json[innerKey]=jsonValues;
}
json1[outerKey]=json;
}
try jsonlint.com to validate your JSON
This is valid:
{
"Center": "radio_Required_Center_0,radio_Required_Center_1,",
"Left": "radio_Required_Left_0,"
}
This is valid too:
{
"Required": {
"Center": "radio_Required_Center_0,radio_Required_Center_1,",
"Left": "radio_Required_Left_0,"
}
}
This isn't:
Required: {
"Center": "radio_Required_Center_0,radio_Required_Center_1,",
"Left": "radio_Required_Left_0,"
}
using JSON.stringify() is the right way of converting javascript objects to JSON string format. However if you want to put it in a variable you should do that first, later in the last step you convert to JSON string.
var output = { "Required": yourpreviousjsonvar },
jsonString = JSON.strinify(output);
EDIT:
You need to process the data first you probably won't even need the JSON string if I understand you right. (=> if however you already got a string you need it parsed first. Do it using JSON.parse(yourjsonstring))
Fetch the outer-key (Required or there can be other also).
Fetch all values under the key Center and Left
Create array from the value retrieved from step 2 (split based on ",").
Loop through the values obtained from step 3 and execute the logic.
having this as variable:
var a = {
"Required": {
"Center": "radio_Required_Center_0,radio_Required_Center_1,",
"Left": "radio_Required_Left_0,"
}
}
// step 1
console.log(a.Required);
// step 2
console.log(a.Required.Center);
console.log(a.Required.Left);
// step 3
var center = a.Required.Center.split(',');
var left = a.Required.Left.split(',');
// step 4
for(var i = 0; i<center.length; i++){
console.log("doing somthing with", center[i]);
}
Here is a fiddle => use Chrome/safari/Opera's developpertools and check the console to check the output. Or use firebug (in firefox) Or IE9 or greater (F12).
Use native Javascript toSource :
var obj= new Object();
var obj1= new Object();
for(firstLoop){
key=outerKey;
for(innerLook){
innerKey=innerkey;
for(lastloop){
jsonValues= create values in a java variable
}
obj.innerKey=jsonValues;
}
obj1.outerKey=obj;
}
json = obj.toSource();
json1 = obj1.toSource();

Categories