I am trying to convert a string i receive back from an API into a JSON object in Angular.
The issue is that the string is not normalized to be parsed into JSON easily.
This is the string im working with:
"{rootCause=EJBusinessException: This is a sample exception thrown for testing additional info field, description=This is a more detailed description about the incident., stackTrace=com.springboot.streams.infrastructure.web.heartbeat.HeartbeatService.testServiceNow(HeartbeatService.java:200)}"
When trying to do JSON.parse(myStr) it throws an error due to invalid string format.
Is there an easy way to convert the listed string into a more correct JSON format, getting rid of the '=' and replacing them with ':' instead.
There is more to it than just .replace(/['"]+/g, ''), as even with that the string is not ready to be turned into JSON yet.
Hoping someone more versed in Javascript knows a trick i dont.
You just need to manipulate the string before parsing it remove unecessary string that can cause error to the object like "{" and "}" and split it by "," example is in below.
var obj = {}, str = "{rootCause=EJBusinessException: This is a sample exception thrown for testing additional info field, description=This is a more detailed description about the incident., stackTrace=com.springboot.streams.infrastructure.web.heartbeat.HeartbeatService.testServiceNow(HeartbeatService.java:200)}"
str.split(",").forEach((st, i) => {
pair = st.split("=")
if(pair.length > 1) {
obj[pair[0].replace("{",'').replace("}", '').trim()] = pair[1]
} else {
obj[i] = pair
}
})
console.log(obj)
As commenters have posted, unless you control the API or at least have documentation that output will always follow a specific format, then you are limited in what you can do. With your current example, however you can trim off the extraneous bits to get the actual data... (remove braces, split on comma, split on equals) to get your key:value pairs... then build a javascript object from scratch with the data... if you need json string at that point can just JSON.stringify()
var initialString = "{rootCause=EJBusinessException: This is a sample exception thrown for testing additional info field, description=This is a more detailed description about the incident., stackTrace=com.springboot.streams.infrastructure.web.heartbeat.HeartbeatService.testServiceNow(HeartbeatService.java:200)}"
var trimmedString = initialString.substr(1, initialString.length - 2);
var pairArray = trimmedString.split(',');
var objArray = [];
pairArray.forEach(pair => {
var elementArray = pair.split('=');
var obj = {
key: elementArray[0].trim(),
value: elementArray[1].trim()
};
objArray.push(obj);
});
var returnObj = {};
objArray.forEach(element => {
returnObj[element.key] = element.value;
});
console.log(JSON.stringify(returnObj));
Related
I am working on a project where I require to format incoming numbers in the following way:
###.###
However I noticed some results I didn't expect.
The following works in the sense that I don't get an error:
console.log(07);
// or in my case:
console.log(007);
Of course, it will not retain the '00' in the value itself, since that value is effectively 7.
The same goes for the following:
console.log(7.0);
// or in my case:
console.log(7.000);
JavaScript understands what I am doing, but in the end the actual value will be 7, which can be proven with the following:
const leadingValue = 007;
const trailingValue = 7.00;
console.log(leadingValue, trailingValue); // both are exactly 7
But what I find curious is the following: the moment I combine these two I get a syntax error:
// but not this:
console.log(007.000);
1) Can someone explain why this isn't working?
I'm trying to find a solution to store numbers/floats with the exact precision without using string.
2) Is there any way in JS/NodeJS or even TypeScript to do this without using strings?
What I currently want to do is to receive the input, scan for the format and store that as a separate property and then parse the incoming value since parseInt('007.000') does work. And when the user wants to get this value return it back to the user... in a string.. unfortunately.
1) 007.000 is a syntax error because 007 is an octal integer literal, to which you're then appending a floating point part. (Try console.log(010). This prints 8.)
2) Here's how you can achieve your formatting using Intl.NumberFormat...
var myformat = new Intl.NumberFormat('en-US', {
minimumIntegerDigits: 3,
minimumFractionDigits: 3
});
console.log(myformat.format(7)); // prints 007.000
Hi
You can use an aproach that uses string funtions .split .padStart and .padEnd
Search on MDN
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/split
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/padStart
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/padEnd
Here you have an example:
const x = 12.1;
function formatNumber( unformatedNumber) {
const desiredDecimalPad = 3;
const desiredNonDecimalPad = 3;
const unformatedNumberString = unformatedNumber.toString();
const unformatedNumberArr = unformatedNumberString.split('.');
const decimalStartPadded = unformatedNumberArr[0].padStart(desiredDecimalPad, '0');
const nonDecimalEndPadded = unformatedNumberArr[1].padEnd(desiredNonDecimalPad, '0');
const formatedNumberString = decimalStartPadded + '.' + nonDecimalEndPadded;
return formatedNumberString;
}
console.log(formatNumber(x))
Im currently stuck trying to convert a string into JSON in javascript.
the string im getting from the server is:
"{knee=true, centered=true}"
the outcome im looking for is something like this:
{ knee: true, centered: true}
but since the string is using equals and there are missing quotes the JSON.parse isnt working, I dont know how to solve this. any help will be appreciated, thank you!
The best I could do was this ... It returns value of object in strings though it seems to work perfect ! ( Actually this one challenged me so I had to do it ) :-)
let str = "{knee = true, centered = true}";
str = str.replaceAll('{', '')
str = str.replaceAll('}', '')
str = str.split(",")
str = Object.assign({}, str);
let key_value;
let key;
let val;
for (var i = 0; i < Object.keys(str).length; i++) {
key_value = str[i].split("=");
key = String(key_value[0]);
val = key_value[1];
str[i] = val;
delete Object.assign(str, {[key]: str[i]
})[i];
}
console.log(str)
Assuming you don't have nested things or strings with commas or brackets in them, you could replace all { with {", = with ":, and , with , ":
const str = "{knee=true, centered=true}"
console.log(
JSON.parse(str.split('{').join('{"').split('=').join('":').split(', ').join(', "'))
)
Without more specifics it's impossible to verify how correct this is, but if I was to make some assumptions:
An object is a set of key/value pairs surrounded by { and }
Key/value pairs are separated by ,
Any arbitrary whitespace is allowed around key/value pairs
A key and value are separated by a =
Values can only hold the value true or false which should be translated to a JavaScript boolean
...then parsing can be done through some regular expressions and string manipulations.
const objectRegExp = /^\{(.*)}$/;
function parseNJson(str) { // notJSON
const match = objectRegExp.exec(str);
if (!match) {
throw new Error('This is not NJson');
}
const [, keyValuesBlock] = match;
const keyValueStatements = keyValuesBlock.split(',');
const keyValues = keyValueStatements.map(statement => statement.split('='));
return keyValues.reduce((result, [keyStr, valueStr]) => {
const key = keyStr.trim();
const trimmedValue = valueStr.trim();
let value;
if (trimmedValue === 'true') {
value = true;
} else if (trimmedValue === 'false') {
value = false;
} else {
throw new Error(`Unsupported value ${trimmedValue}`);
}
return Object.assign(result, { [key]: value });
}, {});
}
This will easily fall apart if any assumptions were incorrect, like "what if values can be strings? What if strings can be quoted with double quotes? What if they can also be surrounded by single quotes? What if numbers are supported? What if hexadecimal numbers are supported?"
If the data being sent on the server is a standard format, they should be able to tell you "this was formatted as X" so you can find a spec-compliant X parser. Or you could insist data is sent as JSON instead, since that's a super common exchange format. The best thing is that the server and client are using a common, well-defined message formatting spec so you don't accidentally break things whenever receiving or sending data that has characteristics you didn't account for.
I have javascript function that calls an external Api and returns in most case a valid JSON string.
function (successResponse) {
{
console.log(successResponse);
}
However, in some cases it return the the following invalid JSON
Response: Status=200, Text: {"createdTime":"2017-05-08T14:47:56Z","lastUpdatedTime":"2017-05-08T14:47:56Z","createdMode":"API","uuid":"e333c1-3599-36d7-9ef5-dc22c79a4a52","userId":"anonymous"}, Error Message: null
How can I parse the above string to get the 'uuid'
Thanks
If you're expecting a response string in that format, you can use a regular expression to extract the "text" portion of the response:
function (successResponse) {
{
var responseText = successResponse.match(/\{.+\}/);
var responseTextJSON = JSON.parse(responseText);
var uuid = responseTextJSON.uuid;
console.log(uuid);
}
Maybe you can parse the string yourself to exclude everything outside of {} ?
var apiResponse = 'Response: Status=200, Text: {"createdTime":"2017-05-08T14:47:56Z","lastUpdatedTime":"2017-05-08T14:47:56Z","createdMode":"API","uuid":"e333c1-3599-36d7-9ef5-dc22c79a4a52","userId":"anonymous"}, Error Message: null';
var apiResponse_fixed = apiResponse.substring((apiResponse.indexOf("{") - 1), (apiResponse.lastIndexOf("}") + 1));
var json_obj = JSON.parse(apiResponse_fixed);
console.log(json_obj.uuid);
Replace the non-JSON features, and then interpret as JSON
Looks like the server owner has been a bit lazy, and programmed an error response which contains a JSON-like interior section but surrounded by a couple of non-JSON elements.
If you are desperate to resolve the situation and have no ability to fix the server output format, here is my suggestion:
notQuiteJson = 'Response: Status=200, Text: {"createdTime":"2017-05-08T14:47:56Z","lastUpdatedTime":"2017-05-08T14:47:56Z","createdMode":"API","uuid":"e333c1-3599-36d7-9ef5-dc22c79a4a52","userId":"anonymous"}, Error Message: null';
madeJson = notQuiteJson.replace('Response: Status=200, Text:','{"Response": {"Status":200}, "Text":').replace('Error Message: null','"ErrorMessage": null}')
obj = JSON.parse(madeJson)
console.log(obj.Text.uuid) // Result: "e333c1-3599-36d7-9ef5-dc22c79a4a52"
Of course this only works if the error message is always exactly this. In reality you may want to use a 3-digit wildcard to cover a range of "Status=" codes. But then you would have to also be confident that all the error modes produce the same non-JSON text at the start and end of the response.
Disclaimer
#sp00m and #Bergi, don't kill me: you are right of course, but this is just for if the poster has no choice in the matter 8-)
I want to carry out variable substitutions on a string (I've already ruled out template literals because the string has to be stored and evaluated later).
Mustache or something like it would seem like a contender, but I want to know if the substitution was incomplete. In this case, it's to produce urls, so missing parts mean invalid urls:
Testing this out in node:
var Mustache = require('mustache');
var result = Mustache.render("/someurl/{{path1}}/{{path2}}/", {path1:"my-path-to-1"})
console.log(`result:${result}:`)
This happens without a problem, but the resulting url is useless because Mustache silently replaced the missing path2 with an empty string. What I would like to see is an exception getting thrown (best) or failing that an easy way to recognize that not everything was substituted.
Note: the template string is arbitrary and so are the substitution object's contents.
output:
result:/someurl/my-path-to-1//:
This is the Python equivalent that I am looking for:
res = "/someurl/%(path1)s/%(path2)s/" % {"path1":"my-path-to-1"}
output:
KeyError: 'path2'
I ended up using sprintf, which has the benefit of having a different format than Mustache (or Django) so that you can embed it in data-url or the like:
const sprintf = require("sprintf-js").sprintf;
var o_substit = {
path1 : "mypath1"
};
var T_URL = "/someurl/%(path1)s/%(path2)s/";
console.log(`\nT_URL:${T_URL}, substitutions:`);
try {
console.dir(o_substit);
console.log("expecting a failure...")
var url = sprintf(T_URL, o_substit);
console.log(` url:${url}:`);
}
catch (e){
console.log(` exception:${e}`);
};
var o_substit = {
path1 : "mypath1"
,path2 : "mypath2"
};
console.log(`\nT_URL:${T_URL}, substitutions:`);
try{
console.dir(o_substit);
console.log("\nexpecting a success:")
var url = sprintf(T_URL, o_substit);
console.log(` url:${url}:`);
}
catch (e){
console.log(` exception:${e}`);
};
output:
T_URL:/someurl/%(path1)s/%(path2)s/, substitutions:
{ path1: 'mypath1' }
expecting a failure...
exception:Error: [sprintf] property 'path2' does not exist
T_URL:/someurl/%(path1)s/%(path2)s/, substitutions:
{ path1: 'mypath1', path2: 'mypath2' }
expecting a success:
url:/someurl/mypath1/mypath2/:
Hey all im not every good with regexp i was hoping someone could help.
ok so this is the sting "KEY FOUND! [ 57:09:91:40:32:11:00:77:16:80:34:40:91 ]"
And i need to pull "57:09:91:40:32:11:00:77:16:80:34:40:91", now this key can be meany length not just as written here and with or with out the ":"
now the second sting i would like to test and extract is: "[00:00:09] Tested 853 keys (got 179387 IVs)", i would like to pull "00:00:09" and "853" and "179387".
this would be the raw string http://regexr.com?31pcu or http://pastebin.com/eRbnwqn7
this is what im doing now.
var pass = new RegExp('KEY FOUND\!')
var tested = new RegExp('Tested')
var fail = new RegExp('\Failed. Next try with ([0-9]+) IVs')
var data="Look at the link i added"
if (tested.test(data)) {
self.emit('update', mac, {
'keys' : data.split('Tested ')[1].split(' keys ')[0],
'ivs' : data.split('got ')[1].split(' IVs')[0]
});
} else if (pass.test(data)) {
var key = data.split('KEY FOUND! [')[1].split(' ]')[0].split(':').join('');
} else if (fail.test(data)) {
console.log(data);
}
thanks all
Edit:
I have added more the the question to help with the answer
If it is always surrounded by [] then it is simple:
\[([\s\S]*)\]
This will match any characters enclosed by [].
See it in action here.