How to parse and concatenate whit specific separator - javascript

My problem is that I have to concatenate all the text after the "product_link_href": in a huge serie of things (there are 200+ of these so I couldn't post the entire thing) like:
Solved snippet removed for privacy reasons
It's coming from an api, it's white in windows power shell, the name of the thing is response.data I'm using axios; I think this thing to the machine is just plain text, because it was green before I selected it whit .data ; but I still need all the text after "product_link_href": concatenated, in text format and sepsarated by ","
The code I am using is
axios.get('https://randomapi/' + id + '/json?api_token=examplenotrealapitoken').then(response => {
console.log(response.data);
});
I tried JSON.parse and stringify but nothing works.

The response from the server is stringified JSON objects that have been concatenated with line return characters "\n".
It is not JSON parseable because it is not an array, which it needs to be, to be valid JSON.
The approach I took is to coerce it to "an array of stringified JSON objects". Since each object is shallow, there is no nesting, so the } character is unambiguously the end of a stringified object.
You can call massiveJSONishString.split('}'), and you get an array of JSON-stringified objects with the trailing } missing on each one.
Then you map over that array, and for each element, add the trailing } that we threw away to array-ify it, and JSON.parse() that string, producing an array of JSON objects.
This is the code you are looking for:
const textArray = res.data.split("}");
const jsonArray = textArray.map(element => {
try {
return JSON.parse(`${element}}`);
} catch (e) {
return {
product_link_href: "MALFORMED JSON"
};
}
});
// console.log(jsonArray);
const product_link_hrefs = jsonArray.map(obj => obj.product_link_href);
const list = product_link_hrefs.join(", ");
console.log(list);
console.log(`You're welcome!`);

Related

Remove special character from AsyncStorage getitem data

I'm getting AsyncStorage data but there i'm getting special character \ which was not there when i set the item. Don't know why this is being added. Anyway i'm trying to remove this character from my data. I have tried the following way to do that:
data = ["{\"word\":\"Cat\",\"pronunciation\":null,\"definitions\":[{\"type\":\"noun\",\"definition\":\"a small domesticated carnivorous mammal with soft fur, a short snout, and retractile claws. It is widely kept as a pet or for catching mice, and many breeds have been developed.\",\"example\":\"their pet cat\",\"image_url\":\"https://media.owlbot.info/dictionary/images/aaaaaaaaaaaaaaaaac.jpg.400x400_q85_box-42,0,943,900_crop_detail.jpg\",\"emoji\":\"🐈\"}]}",
var b=JSON.stringify(data);
var str = b.replace(/\\/g, '');
var final = JSON.parse(str);
console.log(final);
Now this throws error Unexpected token { in JSON at position 3 . How can i resolve this?
It looks like you might want to call JSON.parse with the elements within data, rather than data itself. The data variable is an array, but the elements within it are JSON. For example:
const data = [...];
const parsedData = data.map(datum => JSON.parse(datum));

json - can't access json parameter

Here is my code
var data = '{"coord":{"lon":74.34,"lat":31.55},"weather":[{"id":711,"main":"Smoke","description":"smoke","icon":"50d"},{"id":701,"main":"Mist","description":"mist","icon":"50d"}],"base":"cmc stations","main":{"temp":304.6,"pressure":1002,"humidity":62,"temp_min":304.15,"temp_max":305.15},"wind":{"speed":5.1,"deg":130},"clouds":{"all":20},"dt":1466901000,"sys":{"type":1,"id":7133,"message":0.0035,"country":"PK","sunrise":1466899176,"sunset":1466950287},"id":1172451,"name":"Lahore","cod":200}'
setWeather(data);
function setWeather(data) {
var json = JSON.parse(JSON.stringify(data));
alert(json['main']['temp']);
$('#temp').html(json['main']['temp']);
}
And I can't seem to figure out why I'm not able to access the json object parameter. Anyone know what the issue is?
Thanks in advance.
Let us to some basic debugging:
> var data = '{"coord": ... }';
> typeof data
"string"
So far so good, data is a string.
> JSON.stringify(data);
""{\"coord\": ... }""
> typeof JSON.stringify(data);
"string"
Apparently JSON.stringify(data) also returns a string. We can see the same value contained in data but now including surrounding quotes (note the double "" at the beginning and the end) and escaped quotes (\").
So what exactly does JSON.stringify do? It will convert any JavaScript value to JSON. Some examples:
> JSON.stringify([]) // array
"[]"
> JSON.stringify(true) // array
"true"
> JSON.stringify("foo") // string
""foo""
We can see that passing a string simply produces another JSON encoded string, so that doesn't seem particular helpful. But you are also using JSON.parse, so lets see what effect that has:
> JSON.parse(JSON.stringify(data))
"{"coord": ... }"
> typeof JSON.parse(JSON.stringify(data))
"string"
It seems using JSON.parse returns a string again. This shouldn't be too surprising since we are passing a string value to JSON.stringify, which will encode it as a JSON string. Parsing this result must give us back the original value, which was a string. We can verify that easily:
> JSON.parse(JSON.stringify(data)) === data
true
Yep.
So that doesn't help us converting data to a JavaScript object. Lets just try JSON.parse instead:
> JSON.parse(data)
Object {coord: Object, weather: Array[2], base: "cmc stations", main: Object, wind: Object…}
That looks much better. Since data contains a JSON encoded object, JSON.parse converts that value to a JavaScript object.
I your example, data is a string, not a javascript object, so you don't need to use JSON.stringify, remove it and it should work:
var data = '{"coord":{"lon":74.34,"lat":31.55},"weather":[{"id":711,"main":"Smoke","description":"smoke","icon":"50d"},{"id":701,"main":"Mist","description":"mist","icon":"50d"}],"base":"cmc stations","main":{"temp":304.6,"pressure":1002,"humidity":62,"temp_min":304.15,"temp_max":305.15},"wind":{"speed":5.1,"deg":130},"clouds":{"all":20},"dt":1466901000,"sys":{"type":1,"id":7133,"message":0.0035,"country":"PK","sunrise":1466899176,"sunset":1466950287},"id":1172451,"name":"Lahore","cod":200}'
setWeather(data);
function setWeather(data) {
//NOTE: only parse is needed
var json = JSON.parse(data);
alert(json['main']['temp']);
$('#temp').html(json['main']['temp']);
}
data is a String because of the single quotes , so if you called JSON.stringify(data) will add another double quotes to data , which means in order to convert data to JS object you will need to call JSON.parse(data) two times .
var obj ='{hello:1}'; //string
var json= JSON.stringify(obj);
console.log(json); // "\"{hello:1}\""
console.log(JSON.parse(json)); //"{hello:1}" => still a string
To get your code running correctly by converting data to object , just remove the JSON.stringify()
function setWeather(data) {
var json = JSON.parse(data); // remove JSON.stringify() => now json is object
alert(json['main']['temp']);
$('#temp').html(json['main']['temp']);
}

How can you parse NON wellformed JSON (maybe using jQuery)

Is there a way to parse NON wellformed JSON, other than using eval?
The background is, that I'm using data tag values to draw a graph like this:
<div id="data" data-idata="[1,2,3]" data-sdata="['foo','bar','baz']"></div>
This works flawlessly with numeric values, these values are delivered as an array directly in jQuery data, no need to parse JSON here.
However, for the labels a string array is to be passed. eval can parse the string in sdata just fine, but JSON.parse and jQuery.parseJSON fail, because it's not wellformed JSON.
var $data = $("#data").data(),
values;
// use eval
out("#out", eval($data.sdata)); // works...
// use JSON.parse
try
{
values = JSON.parse($data.sdata);
} catch(e) {
// silent catch
}
out("#out1", values); // values is undefined
I put together a JsFiddle here to check the thing.
You get error because ['foo','bar','baz'] contains single-quotation marks. JSON RFC specifies that string should be enclosed in double-quotation marks.
There could be a few work-arounds.
Switch quotation marks in the data- attributes:
<tag data-sdata='["foo","bar","baz"]' />
Or replace in Javascript:
values = JSON.parse($data.sdata.replace("'","\""));
You don't need to parse. Simply use .data(), the function does it for you.
I have changed your HTML, I have swapped quotes in line data-sdata="['foo', 'bar', 'baz']" as JSON should use in double-quotation(") marks.
HTML
<div id="data" data-idata="[1,2,3]" data-sdata='["foo", "bar", "baz"]'></div>
Script
out("#out1", $("#data").data('idata'));
out("#out2", $("#data").data('sdata'));
DEMO
Ofcourse you cannot easy parse corrupted data for 100% this goes for any data-formats and not only JSON.
If the reason the data are malformed are always the same you should fix it with some str_find and replacement functions.
If it is irregular you have no real chance except writing a really intelligenz and big algorithm. The best way here would be to try to extract the real raw data out of the corrupted string and build a real JSON string with valid syntax.
Try
html
<div id="data" data-idata="[1,2,3]" data-sdata='["foo","bar","baz"]'></div>
<div id="out1">out1</div>
<div id="out2">out2</div>
js
$(function () {
var out = function (outputId, elem, dataId) {
return $.each(JSON.parse($(elem).get(0).dataset["" + dataId])
, function (index, value) {
$("<ul>").html("<li>" + index + " -> " + value + "</li>")
.appendTo(outputId);
});
};
out("#out1", "#data", "idata");
out("#out2", "#data", "sdata");
});
jsfiddle http://jsfiddle.net/guest271314/4mJBp/

Line-oriented streams in Node.js

I'm developing a multi-process application using Node.js. In this application, a parent process will spawn a child process and communicate with it using a JSON-based messaging protocol over a pipe. I've found that large JSON messages may get "cut off", such that a single "chunk" emitted to the data listener on the pipe does not contain the full JSON message. Furthermore, small JSON messages may be grouped in the same chunk. Each JSON message will be delimited by a newline character, and so I'm wondering if there is already a utility that will buffer the pipe read stream such that it emits one line at a time (and hence, for my application, one JSON document at a time). This seems like it would be a pretty common use case, so I'm wondering if it has already been done.
I'd appreciate any guidance anyone can offer. Thanks.
Maybe Pedro's carrier can help you?
Carrier helps you implement new-line
terminated protocols over node.js.
The client can send you chunks of
lines and carrier will only notify you
on each completed line.
My solution to this problem is to send JSON messages each terminated with some special unicode character. A character that you would never normally get in the JSON string. Call it TERM.
So the sender just does "JSON.stringify(message) + TERM;" and writes it.
The reciever then splits incomming data on the TERM and parses the parts with JSON.parse() which is pretty quick.
The trick is that the last message may not parse, so we simply save that fragment and add it to the beginning of the next message when it comes. Recieving code goes like this:
s.on("data", function (data) {
var info = data.toString().split(TERM);
info[0] = fragment + info[0];
fragment = '';
for ( var index = 0; index < info.length; index++) {
if (info[index]) {
try {
var message = JSON.parse(info[index]);
self.emit('message', message);
} catch (error) {
fragment = info[index];
continue;
}
}
}
});
Where "fragment" is defined somwhere where it will persist between data chunks.
But what is TERM? I have used the unicode replacement character '\uFFFD'. One could also use the technique used by twitter where messages are separated by '\r\n' and tweets use '\n' for new lines and never contain '\r\n'
I find this to be a lot simpler than messing with including lengths and such like.
Simplest solution is to send length of json data before each message as fixed-length prefix (4 bytes?) and have a simple un-framing parser which buffers small chunks or splits bigger ones.
You can try node-binary to avoid writing parser manually. Look at scan(key, buffer) documentation example - it does exactly line-by line reading.
As long as newlines (or whatever delimiter you use) will only delimit the JSON messages and not be embedded in them, you can use the following pattern:
let buf = ''
s.on('data', data => {
buf += data.toString()
const idx = buf.indexOf('\n')
if (idx < 0) { return } // No '\n', no full message
let lines = buf.split('\n')
buf = lines.pop() // if ends in '\n' then buf will be empty
for (let line of lines) {
// Handle the line
}
})

convert "converted" object string to JSON or Object

i've following problem and since i upgraded my prototypeJS framework.
the JSON parse is not able anymore to convert this string to an object.
"{empty: false, ip: true}"
previously in version 1.6 it was possible and now it needs to be a "validated" JSON string like
'{"empty": false, "ip": true}'
But how can i convert the 1st example back to an object?
JSON needs all keys to be quoted, so this:
"{empty: false, ip: true}"
is not a valid JSON. You need to preprocess it in order to be able to parse this JSON.
function preprocessJSON(str) {
return str.replace(/("(\\.|[^"])*"|'(\\.|[^'])*')|(\w+)\s*:/g,
function(all, string, strDouble, strSingle, jsonLabel) {
if (jsonLabel) {
return '"' + jsonLabel + '": ';
}
return all;
});
}
(Try on JSFiddle) It uses a simple regular expression to replace a word, followed by colon, with that word quoted inside double quotes. The regular expression will not quote the label inside other strings.
Then you can safely
data = JSON.parse(preprocessJSON(json));
It makes sense that the json parser didn't accept the first input as it is invalid json. What you are using in the first example is javascript object notation. It's possible to convert this to an object using the eval() function.
var str = "({empty: false, ip: true})";
var obj = eval(str);
You should of course only do this if you have the guarantees the code you'll be executing is save.
You can find more information about the json spec here. A json validator can be found here.
edit: Thai's answer above is probably a better solution
const dataWithQuotes = str.replace(/("(\\.|[^"])*"|'(\\.|[^'])*')|(\w+)\s*:/g, (all, string, strDouble, strSingle, jsonLabel) => {
if (jsonLabel) {
return `"${jsonLabel}": `;
}
return all;
});
return dataWithQuotes
similar solution as above , but updated with arrow functions.

Categories