将字符串转换为对象层次

时间:2015-07-09 17:04:18

标签: javascript string paypal paypal-adaptive-payments

我从API返回了以下字符串,我想使用javascript将其转换为对象层次结构。

收到的字符串是:

"paymentInfoList.paymentInfo(0).receiver.amount":"12.00"

我想将其转换为javascript对象,如:

{
    paymentInfoList: {
        PaymentInfo: [{
             receiver: {
                 amount: 12.0
             }
        }]
    }
}

我可以编写自己的解析器,但想知道是否已有一些代码。

更新

根据@JasonCust的答案,这里有一个解析器来解析PayPal自适应付款方式的完整响应: https://github.com/danielflippance/paypal-ap-parser

2 个答案:

答案 0 :(得分:2)

我不知道处理该格式的现有解析器。也许在Paypal的开发者网站上有什么东西?如果您自己滚动,可以使用递归函数,如下例所示。我还没有对它进行过彻底的测试,但它是一个很容易做到的POC。

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>');
&#13;
&#13;
&#13;

或者如果您想使用lodash,可以使用_.set()

var newObj = _.set({}, pair[0].replace(/\(/g, '[').replace(/\)/g, ']'), pair[1]);

&#13;
&#13;
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>');
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.10.0/lodash.min.js"></script>
&#13;
&#13;
&#13;

答案 1 :(得分:2)

由于我无法抗拒一个小谜题,这里有一个干净的递归解决方案,适用于你给出的输入(向下滚动并查看一个小游乐场的片段):

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>