Extract stream to JSON in JS - javascript

Help figuring out how to convert following string to JSON in javascript . I require date(20181218-20181228) and its corresponding price(formattedPrice=$469). Thanks!
20181218-20181228={currencyCode=USD, totalPrice=469.4, formattedPrice=$469, cheapest=false},
20181218-20181226={currencyCode=USD, totalPrice=469.4, formattedPrice=$469, cheapest=false},
20181218-20181227={currencyCode=USD, totalPrice=451.4, formattedPrice=$451, cheapest=false},
Tried adding quotes and : to the text but facing error while parsing because the key(20181218-20181228) isn't specific

You can use .split() and .reduce() like this;
function parseWeirdString(str) {
return str.split(/},?/g).reduce((obj, row) => {
const rowParts = row.split(/\={/);
if (rowParts.length > 1) {
obj[rowParts[0].trim()] = rowParts[1].split(/,/g).reduce((innerObj, keyValue) => {
const keyValueParts = keyValue.split(/=/);
innerObj[keyValueParts[0].trim()] = keyValueParts[1].trim();
return innerObj;
}, {});
}
return obj;
}, {});
}
Should return an object like this:
{
"20181218-20181228": {
"currencyCode": "USD",
"totalPrice": "469.4",
"formattedPrice": "$469",
"cheapest": "false"
},
"20181218-20181226": {
"currencyCode": "USD",
"totalPrice": "469.4",
"formattedPrice": "$469",
"cheapest": "false"
},
"20181218-20181227": {
"currencyCode": "USD",
"totalPrice": "451.4",
"formattedPrice": "$451",
"cheapest": "false"
}
}
Note that all values are strings including "true" and "false". and if the values have commas etc then this will fail.

Replace all = with : using replace all, Remove "," in the end, Put { and } in start and end. All the non-number and non-boolean values should be put in "". You can write a regex for that. Let me know if you need help in that.
objstr = `{"20181218-20181228":{"currencyCode":"USD", "totalPrice":469.4, "formattedPrice":"$469", "cheapest":false},
"20181218-20181226":{"currencyCode":"USD", "totalPrice":469.4, "formattedPrice":"$469", "cheapest":false}}`;
//replace, remove last , ,,, Put {} in start and end ,,,,
obj = JSON.parse(objstr);
console.log(obj);
You can use below Regex to parse this object. I have created a custom regex for your need which you can customize. There are some other options like eval but are not secure. btw since you are new so informing you that you can upvote(like) answers helping you :)
objstr22 = `{20181218-20181228={currencyCode=USD, totalPrice=469.4, formattedPrice=$469, cheapest=false},
20181218-20181226={currencyCode=USD, totalPrice=469.4, formattedPrice=$469, cheapest=false},
20181218-20181227={currencyCode=USD, totalPrice=451.4, formattedPrice=$451, cheapest=false}}`;
objstr22 = objstr22
.replace(/ /g, "")
.replace(/([\-\w\d]+)=/g, '"$1"=')
.replace(/=([\w\d\.\$]+)/g, ':"$1"')
.replace(/=([[{])/g, ":$1");
console.log(objstr22);
let obj22 = JSON.parse(objstr22);
for (o of Object.keys(obj22)) {
console.log(o, obj22[o]);
}

Related

Nested replace of strings with double quotes in Javascript

In Logic Apps I have this function which replaces double double quotes with a zero for some strings.
How can I replicate this in Javascript?
replace(replace(replace(replace(replace(body('HTTP_2'),'"PR_RENT":""','"PR_RENT":0'),'"PR_ID":""','"PR_ID":0'),'"PR_USUM":""','"PR_USUM":0'),'"PR_LEAS":""','"PR_LEAS":0'),'"PR_USER8":""','"PR_USER8":0')
I tried this code.
```
var json = workflowContext.actions.HTTP_2.outputs.body
if (json.PR_RENT=="\"\"")
{
json.PR_RENT=0
}
if (json.PR_ID=="\"\"")
{
json.PR_ID=0
}
if (json.PR_USUM=="\"\"")
{
json.PR_USUM=0
}
if (json.PR_LEAS=="\"\"")
{
json.PR_LEAS=0
}
if (json.PR_USER8=="\"\"")
{
json.PR_USER8=0
}
return json;
```
and got error messages like this for all the affected fields.
```[
{
"message": "Invalid type. Expected Integer but got String.",
"lineNumber": 0,
"linePosition": 0,
"path": "Payload[0].PR_USER8",
"value": "",
"schemaId": "#/properties/Payload/items/properties/PR_USER8",
"errorType": "type",
"childErrors": []
},
,
{
"message": "Invalid type. Expected Integer but got String.",
"lineNumber": 0,
"linePosition": 0,
"path": "Payload[2].PR_RENT",
"value": "",
"schemaId": "#/properties/Payload/items/properties/PR_RENT",
"errorType": "type",
"childErrors": []
}
]
Here is some of my JSON code
```{"Payload":[{"RLS_GROUP":"","PR_SNAM":"700063","PR_OWN":"qqq","PR_REF":"","PR_NAME":"Bqqq12","PR_ADD1":"qqq","PR_ADD2":"INDUSTRIAL ESTATE","PR_ADD3":"23 INDUSTRIAL ESTATE","PR_ADD4":"yyy","PR_ADD5":"","PR_ADD6":"GB","PR_POST":"WQDQWD","PR_TEL":"23213","PR_TELX":"21312312","PR_FAX":"","PR_CONT":"","PR_NUNIT":"","PR_INT":"","PR_TENR":"LEASED","PR_QDAY":"","PR_CLSS":"","PR_DRCT":"Closing","PR_AGENT":"","PR_NOWN":"","PR_BOWN":"","PR_SOL":"","PR_HSTT":"","PR_HEND":"","PR_HAMT":"","PR_PFREQ":"","PR_NTENT":"","PR_NFLR":"","PR_GRA":"","PR_WATER":"","PR_RATVAL":"","PR_RTCT":"","PR_SCHG":"","PR_OCHG":"","PR_GFA":"","PR_ZONEA":"","PR_ZONEB":"","PR_ZONEC":"","PR_UPDATE":"","PR_UTIME":"","PR_UUSER":"","PR_HIST":"","PR_TAXYN":"","PR_TAX":"","PR_START":"","PR_END":"","PR_FREQ":"","PR_QTR":"","PR_NDUE":"","PR_TAXRUN":"","PR_OUTLET":"","PR_INLET":"","PR_VAL":"","PR_CST":"","PR_FRWA":"","PR_FRWB":"","PR_PRINT":"","PR_NL":"","PR_CURRS":"","PR_NEXTS":"","PR_VAT":"D","PR_USER":"","PR_VQDAY":"","PR_OBS1":"STANDARD NORTH","PR_TYPE":"Property","PR_VATDATE":"","PR_FUTHER":"","PR_RESTEN":"","PR_CAPGOODS":"","PR_INSEE":"","PR_CURR":"","PR_AQDATE":"20190917","PR_USER1":"Office","PR_USER2":"Yes","PR_USER3":"","PR_USER4":"","PR_USER5":"20190917","PR_USER6":"","PR_USER7":"","PR_USER8":0,"PR_USER9":"","PR_USER10":"","PR_OBS2":"","PR_OBS3":"","PR_OBS4":"","PR_OBS5":"","PR_OBS6":"","PR_OBS7":"UK","PR_OBS8":"","PR_OBS9":"","PR_SOLD":"0","PR_DATESOLD":"20200917","PR_LAND":"","PR_LANDUM":"","PR_FREE":"","PR_ID":0,"PR_BTYP":"F","PR_LEAS":0,"PR_RENT":999999,"PR_USUM":0,"PR_FBUI":0,"PR_DREN":"","PR_USRC":"","PR_RSRC":"","PR_LSRC":"","PR_ELSR":"","PR_EGRS":"","PR_PROR":"","PR_BSTA":"","PR_LNAM":"123123213","PR_SITE":"","PR_REGION":"","PR_DESC":""}]}
I have to do this because the API is returning "" for integer fields instead of zero when there is no value.
I tried this code
var json = workflowContext.actions.HTTP_2.outputs.body;
json.Payload[0].RLS_GROUP='Test';
json.Payload[0].PR_REF=123;
return json;
and got this message
InlineCodeScriptRuntimeFailure. The inline code action 'JavaScriptCode'
execution failed, with error 'Cannot read property '0' of undefined'.
Also, my Javascript action screen looks a bit different to yours.
I tried this code. It seems to have worked for the first example, but not all examples. Perhaps the data contains a space before the double double quotes.
How do I iterate through all payload elements?
var jsonString = workflowContext.actions.HTTP_2.outputs.body;
const json =JSON.parse(jsonString);
const dic = json['Payload'][0];
const checkFields = ['PR_RENT','PR_ID','PR_USUM','PR_LEAS','PR_USER8'];
checkFields.forEach(field=>{
console.log(dic[field]);
if(dic[field]=='""')
{
dic[field]=0;
console.log(field);
}
}
);
return json;
If you want to use JavaScript to manage the json, just set the value directly. You could refer to my actions as the below pic show. The expression would be like json.key=value;
Update: I test with the array json it could work, you need to point the index. If not please provide more information.
This treats the json as a string and not an array.
json=json.replace(/"PR_USER8":""/g,'"PR_USER8":0').replace(/"PR_RENT":""/g,'"PR_RENT":0').replace(/"PR_ID":""/g,'"PR_ID":0').replace(/"PR_USUM":""/g,'"PR_USUM":0').replace(/"PR_LEAS":""/g,'"PR_LEAS":0');
return json;```
I think this is better as it treats the json as an object not a string.
```
var jsonString = workflowContext.actions.HTTP_2.outputs.body;
const json =JSON.parse(jsonString);
const ret =[];
const dic = json['Payload'];
const checkFields = ['PR_RENT','PR_ID','PR_USUM','PR_LEAS','PR_USER8'];
for(i in json['Payload'])
{
checkFields.forEach(field=>{
if(json.Payload[i][field]=="")
{
json.Payload[i][field]=0;
// console.log(field);
}
}
);
}
return json;
```

how to sanitize object keys in JSON for conversion to XML

I need to remove any slashes from all keys (and sub keys) in a JSON structure in order to convert it to XML, where a slash cannot occur in a tag name.
"langServices": {"en/ENGLISH_ONLY": "English"}
I imagine something along the lines of
var finalData = jsonstr.replace("en/", "en-");
, replacing all slashes with a dash. So it should also work for this: {"can/cancel" : "true"}, where I don't know what string will come before the slash.
var jsonIn = {
"some/other/key/with/slashes": "foo bar baz",
"langServices": {
"en/ENGLISH_ONLY": "English",
"can/cancel": "true"
}
};
function sanitizeKeysRecursively(objIn) {
Object.entries(objIn).forEach(function(kv) {
var sanitizedKey = kv[0].replace(/\//g, "-");
// call the function recursively on any values that are objects
if (typeof kv[1] === 'object') {
sanitizeKeysRecursively(kv[1]);
}
// set the sanitized key and remove the unsanitized one
if (sanitizedKey != kv[0]) {
objIn[kv[0].replace(/\//g, "-")] = kv[1];
delete objIn[kv[0]];
}
});
}
sanitizeKeysRecursively(jsonIn);
console.log(jsonIn);

javascript fix json with regex

Hi All I want to fix my json
I got strings without " and I need to bring them back somehow
I have found a regex that find some of the texts but still its not returning the right result
var newString2 = j.replace(/[a-zA-Z0-9#.,_+]*[^:][\w]/g, function(x){
return '"'+x+'"';
});
my json
{
User_Story_UI_24:
{
Env:Staging,
UserName:9ascf#gmail.com,
Password: User#SDF45sdfg,
Supplier:Xxxxx,
SupplierWebSite:www.xxxx.com,
SupplierPhone:+111 2223334440,
SupplierAddress:sss asf21, asf asf, saf
}
}
the epcepted result
{
"User_Story_UI_24":
{
"Env":"Staging",
"UserName":"9ascf#gmail.com",
"Password": "User#SDF45sdfg",
"Supplier":"Xxxxx",
"SupplierWebSite":"www.xxxx.com",
"SupplierPhone":"+111 2223334440",
"SupplierAddress":"sss asf21, asf asf, saf"
}
}
I've used a regex that detects the lines in your regex (assuming it's in the same format as in your example).
Then it uses a function that receives the matching groups as its parameters and creates two quoted strings accordingly.
The only change I made to your input was adding a comma after the last property, to keep all the lines in the same format:
const input = `{
User_Story_UI_24:
{
Env:Staging,
UserName:9ascf#gmail.com,
Password: User#SDF45sdfg,
Supplier:Xxxxx,
SupplierWebSite:www.xxxx.com,
SupplierPhone:+111 2223334440,
SupplierAddress:sss asf21, asf asf, saf,
}
}`;
let ans = input.replace(/(\w+?): ?([+\w #.,]+),/g, (row, prop, value) => {
return `"${prop}": "${value}",`;
});
console.log(ans);

How to extract the value of an object inside an incomplete JSON array in Javascript?

I have a node app from which I get some data. I have gone through other questions asked on SO..but Im unable to figure this out. I need to access the value of result . The code below shows the exact response I get from server. None of the methods described in other answers like JSON.parse() etc seem to work.
[{
query: {
"parameter1": "12",
"parameter2": "13",
"parameter3": 25
}
result: 6.58443
}]
EDIT : As mentioned in the comments below, unfortunately I cant fix this on the server side(Comes from an external source). I have to deal with this broken JSON on my end and extract the value of result.
EDIT 2 : Yes, there are multiple arrays like this. The content and comma part doesnt change. They are listed one after the other.
Despite the fact you can't receive that data though any library function that expects JSON like jQuery $.ajax() with dataType='json' option (you should use dataType="text" in this case to avoid premature error being triggered I mean).
...you obviously need to fix JSON syntax before parsing it (as I understood you already know).
If it is what you are asking for, your best bet is a regular expression search and replace.
If you know you won't get things such as '{bracket: "}"}' it is pretty simple:
Example:
var wrong = `
[{
"query": {
"parameter1": "12",
"parameter2": "13",
"parameter3": 25
}
"result": 6.58443
}]
`;
var good = wrong.replace(/}(?!\s*[,}\]])/g, '},');
var json = JSON.parse(good);
console.log(json);
This is the simplest example that fixes the input you provided.
Even though it does not fix the same problem after an end of array (']') and, most importantly, if it were fixed it (or simply the string ended with '}' instead of ']' it would added an extra ',' at the end messing up things again.
A more polite approach solving beferementioned issues is to replace the var good = ... row in previous code with this one:
var good = wrong.replace(/(}|])(?!\s*[,}\]])/g, '$1,')
.replace(/,\s*$/, '')
;
Now, you have a valid json object so accessing any property in it is pretty obvious. For example, json[0].result is what you asked for.
On the other hand, if you can have brackets inside literal strings, it will be much more difficult (even not impossible). But I figure out it would hardly be the case...
what you can do is to encapsulate your result with back-ticks to have a (valid) string literal, then get result with any method you want, for example a matching regex :
var arr = `[{
"query": {
"parameter1": "12",
"parameter2": "13",
"parameter3": 25
}
"result": 6.58443
}]`;
var match = arr.match(/("result": )(\d*.\d*)/);
console.log(match[2]);
The suggestions provided above..all point to a hacky way of solving this. The only way to solve this issue was with the help of good old Regex expressions. To my surprise..even though there are lots of libraries to handle JSON parsing etc, to solve edge cases(Common when dealing with small clients or unreliable data source), there is no library which can handle this scenario.
#Bitifet's answer is what solves this problem..with regex.
Purely for illustrative purposes, the below code "rewrites" JSON that is missing commas into JSON that has commas in the appropriate places. The advantage of using this over a replace or a regular expression is that this code guarantees that string literals are handled correctly:
const LEX_EXPR = (
'('
+ '"(?:\\\\(?:["\\\\/bfnrt]|u[a-fA-F0-9]{4})|[^"])*"|'
+ '-?\\d+(?:\\.\\d+)?(?:[eE][+-]?\\d+)?|'
+ '(?:true|false|null)'
+ ')|'
+ '([{\\[])|'
+ '([}\\]])|'
+ '([:,])|'
+ '(\\s+)|'
+ '(.)'
)
function lex(string) {
let tokens = []
let expr = new RegExp(LEX_EXPR, 'mguy')
let match = expr.exec(string)
while(match !== null) {
let [
value,
atom,
begin, end, sep,
whitespace,
junk
] = match
let type
if (atom != null) {
type = "atom"
} else if (begin != null) {
type = "begin"
} else if (end != null) {
type = "end"
} else if (sep != null) {
type = "sep"
} else if (whitespace != null) {
type = "whitespace"
} else {
// junk. ignore or raise exception
throw `Invalid character: ${junk}`
}
tokens.push({ type, value })
match = expr.exec(string)
}
return tokens
}
function shouldInsertComma(prev, cur) {
if (!prev || !cur) {
return false
}
if (prev.type == "begin" || prev.type == "sep") {
return false
}
return cur.type == "begin" || cur.type == "atom"
}
function rewrite(tokens) {
let out = []
let prevNonWhitespace = null
for (let i = 0; i < tokens.length; i++) {
let cur = tokens[i]
if (cur.type !== "whitespace") {
if (shouldInsertComma(prevNonWhitespace, cur)) {
out.push({ type: "sep", value: "," })
}
prevNonWhitespace = cur
}
out.push(cur)
}
return out
}
function joinTokens(tokens) {
return tokens.map(({ value }) => value).join('')
}
const invalid = `
{
"foo": {
"bat": "bing}"
"boo": "bug"
}
"result": "yes"
}
`
const rewritten = joinTokens(rewrite(lex(invalid)))
console.log(JSON.parse(rewritten)) // { foo: { bat: 'bing}', boo: 'bug' }, result: 'yes' }

How to return a result from JSON with case insensitive search using javascript?

My JSON contains 'products' that each have multiple values (name, manufacturer etc.)
I have the following code that allows me to pull 'products' from my JSON based on a search result acquired from a query string. It works fine, but only if the search entry is formatted exactly how it is written in the string.
How can I allow case insensitive searches yield the desired result (and ideally, partial searches)?
I believe that regular expressions are the way to go, but I've exhausted my knowledge and can't seem to get anywhere with it.
I tried to put together a fiddle but couldn't get a proper demo working, so instead I've tried to consolidate the code and comment it for clarity. Any help would be greatly appreciated :)
Parse the JSON:
var prodobjects = JSON.parse(prods);
Code to get products based on specific value:
function getData(array, type, val) {
return array.filter(function (el) {
return el[type] === val;
});
}
Code to retrieve query string:
function gup( name ){
name = name.replace(/[\[]/,"\\\[").replace(/[\]]/,"\\\]");
var regexS = "[\\?&]"+name+"=([^&#]*)";
var regex = new RegExp( regexS );
var results = regex.exec( window.location.href );
if( results == null ) return "";
else return results[1];}
Section of query string I want to use:
var prodresult = gup( 'search' );
Remove plusses and replace with spaces:
var removeplus = prodresult.replace(/\+/g, ' ');
Compile list of products with their 'Prodname' matching the 'search' query:
var searchname = getData(prodobjects.products, 'Prodname', removeplus);
And as requested here is a sample of the JSON. It's still in development so the null values etc. are currently being worked out (it's received through an api). This is just one of the products, but the actual string contains many in the same format (but within "products"):
var prods = JSON.stringify({"products": [
{
"Prodname": null,
"Oem": "Example OEM",
"Snippet": "Example Snippet",
"Linkto": "www.linkhere.com",
"Imagesource": "image.png",
"Category": "Category",
"Tagline": "Tagline goes here",
"Longdescription": [
{
"Paragraph": "<p>First description of the paragraph</p>"
},
null,
null,
null
],
"Features": null,
"Company": false,
"Subscribed": false,
"Tariffs": [
{
"Tarname": "Tariff one",
"Tarpaysched": "Monthly per User",
"Tarcost": "£1"
},
null,
null,
null,
null,
null
],
"Extratariffs": null
}
]
});
---UPDATE---
I managed to get it working to support partial searches and case insensitivity with the following:
function getData(array, type, val) {
return array.filter(function (el) {
if (el[type]!=null && val!=null) {
var seeker = val.toLowerCase();
var rooted = el[type].toLowerCase();
var boxfresh = rooted.indexOf(seeker);
if (boxfresh!=-1) {
return rooted
}
}
});
}
You can convert two strings to lowercase (or uppercase) to make the comparison case-insensitive.
function getData(array, type, val) {
return array.filter(function (el) {
return el[type].toLowerCase() === val.toLowerCase();
});
}
For better searching, you might want to look into fuzzy comparison, which is "a search against data to determine likely mispellings and approximate string matching".

Categories