问题
I have the following string returned from an API and I want to convert it to an object hierarchy using javascript.
The string received is:
"paymentInfoList.paymentInfo(0).receiver.amount":"12.00"
I want to convert it to a javascript object like:
{
paymentInfoList: {
PaymentInfo: [{
receiver: {
amount: 12.0
}
}]
}
}
I could write my own parser but wonder if there is some code already out there.
Update
Based on the answer from @JasonCust here is a parser to parse a full response from the PayPal Adaptive Payments Pay method: https://github.com/danielflippance/paypal-ap-parser
回答1:
I don't know of an existing parser that handles that format. Maybe something on Paypal's developer site? If you roll your own you could do so using a recursive function like the example below. I haven't tested it thoroughly but it's a POC that it's easy enough to do.
function setObjVal(obj, paths, val) {
var path;
var arrayInfo;
if (paths.length === 0) {
return val;
}
obj = obj || {};
path = paths.shift();
arrayInfo = path.match(arrayRegExp);
if (arrayInfo) {
path = arrayInfo[1];
if (!Array.isArray(obj[path])) {
obj[path] = [];
}
obj[path][arrayInfo[2]] = setObjVal(obj[path][arrayInfo[2]], paths, val);
}
else {
obj[path] = setObjVal(obj[path], paths, val);
}
return obj;
}
var arrayRegExp = /^(\w+)\((\d+)\)$/;
var input = '"paymentInfoList.paymentInfo(0).receiver.amount":"12.00"';
var pair = input.split(':').map(function (str) { return str.replace(/"/g, ''); });
var newObj = setObjVal({}, pair[0].split('.'), pair[1]);
function setObjVal(obj, paths, val) {
var path;
var arrayInfo;
if (paths.length === 0) {
return val;
}
obj = obj || {};
path = paths.shift();
arrayInfo = path.match(arrayRegExp);
if (arrayInfo) {
path = arrayInfo[1];
if (!Array.isArray(obj[path])) {
obj[path] = [];
}
obj[path][arrayInfo[2]] = setObjVal(obj[path][arrayInfo[2]], paths, val);
}
else {
obj[path] = setObjVal(obj[path], paths, val);
}
return obj;
}
document.write('<pre>' + JSON.stringify(newObj, null, 4) + '</pre>');
Alternatively if you want to use lodash you could use _.set():
var newObj = _.set({}, pair[0].replace(/\(/g, '[').replace(/\)/g, ']'), pair[1]);
var input = '"paymentInfoList.paymentInfo(0).receiver.amount":"12.00"';
var pair = input.split(':').map(function (str) { return str.replace(/"/g, ''); });
var newObj = _.set({}, pair[0].replace(/\(/g, '[').replace(/\)/g, ']'), pair[1]);
document.write('<pre>' + JSON.stringify(newObj, null, 4) + '</pre>');
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.10.0/lodash.min.js"></script>
回答2:
Since I can't resist a little puzzle, here's a clean recursive solution that works for the input you've given (scroll down and view the snippet for a little playground):
function objectFromExpression(expression, value) {
if (!expression) {
return value;
}
var obj = {};
var matchKeyIdxRest = /^(\w+)(?:\((\d+)\))?(?:\.(.+))?$/;
var matches = expression.match(matchKeyIdxRest);
if (!matches) {
throw new Error('Oops! There\'s a problem with the expression at "' + expression + '"');
}
var key = matches[1];
var idx = matches[2];
var rest = matches[3];
var next = objectFromExpression(rest, value);
if (idx) {
var arr = [];
arr[ parseInt(idx) ] = next;
obj[key] = arr;
} else {
obj[key] = next;
}
return obj;
}
function keyValueExpressionToKeyValue(str) {
var matchKeyVal = /^"([^"]+)":"([^"]+)"$/;
var matches = str.match(matchKeyVal);
if (!matches) {
throw new Error('Oops! Couldn\'t extract key and value from input!');
}
return matches.slice(1);
}
var input = '"paymentInfoList.paymentInfo(0).receiver.amount":"12.00"';
var keyAndValue = keyValueExpressionToKeyValue(input);
var key = keyAndValue[0]; // => paymentInfoList.paymentInfo(0).receiver.amount
var value = keyAndValue[1]; // => 12.00
objectFromExpression(key, value);
// => { paymentInfoList:
// { paymentInfo:
// [ { receiver:
// { amount: "12.00" }
// }
// ]
// }
// }
function objectFromExpression(expression, value) {
if (!expression) {
return value;
}
var obj = {};
var matchKeyIdxRest = /^(\w+)(?:\((\d+)\))?(?:\.(.+))?$/;
var matches = expression.match(matchKeyIdxRest);
if (!matches) {
throw new Error('Oops! There\'s a problem with the expression at "' + expression + '"');
}
var key = matches[1];
var idx = matches[2];
var rest = matches[3];
var next = objectFromExpression(rest, value);
if (idx) {
var arr = [];
arr[ parseInt(idx) ] = next;
obj[key] = arr;
} else {
obj[key] = next;
}
return obj;
}
function keyValueExpressionToKeyValue(str) {
var matchKeyVal = /^"([^"]+)":"([^"]+)"$/;
var matches = str.match(matchKeyVal);
if (!matches) {
throw new Error('Oops! Couldn\'t extract key and value from input!');
}
return matches.slice(1);
}
var inputEl = document.getElementById('input');
function onKeyUp() {
var outputEl = document.getElementById('output');
var input = inputEl.value.trim();
try {
var keyAndValue = keyValueExpressionToKeyValue(input);
var key = keyAndValue[0];
var value = keyAndValue[1];
var output = objectFromExpression(key, value);
outputEl.value = JSON.stringify(output, null, 2);
} catch (ex) {
outputEl.value = ex.toString();
}
}
inputEl.addEventListener('keyup', onKeyUp);
inputEl.dispatchEvent(new Event('keyup'));
label, textarea, input { display: block; }
label { font-family: sans-serif; }
input, textarea { font-family: monospace; width: 100%; margin-bottom: 1em; }
textarea { height: 15em; }
<label for="input">Input (type to see changes)</label>
<input id="input" value='"paymentInfoList.paymentInfo(0).receiver.amount":"12.00"'/>
<label for="output">Output</label>
<textarea id="output">Click the "Parse!" button!</textarea>
来源:https://stackoverflow.com/questions/31323965/convert-string-to-object-hierarchy