繁体   English   中英

如何将 x-www-form-urlencoded 字符串转换为 JSON?

[英]How to convert an x-www-form-urlencoded string to JSON?

application/x-www-form-urlencoded 字符串示例

CorrelationId=1&PickedNumbers%5B%5D=1&PickedNumbers%5B%5D=2&PickedNumbers%5B%5D=3&PickedNumbers%5B%5D=4

入JSON

var gamePlayData = {
            CorrelationId: gameId,
            PickedNumbers: ["1","2","3","4"]
        };

这是 Node.js 现在的核心模块: https : //nodejs.org/api/querystring.html#querystring_querystring_parse_str_sep_eq_options

var qs = require('querystring')

var json = qs.parse('why=not&sad=salad')
    // { why: 'not', sad: 'salad' }

也适用于编码字符:

var json2 = qs.parse('http%3A%2F%2Fexample.com&sad=salad')
    // { url: 'http://example.com', sad: 'salad' }

我最近一直在处理这个问题:我必须解析可能包含嵌套多达 5 层深度的对象的数据。 我需要代码既能处理相当复杂的数据,又能解码像id=213这样简单的 URI。

我在谷歌上花了很多时间,试图找到一个(半)优雅的解决方案来解决这个问题,这个问题一直出现。 由于它每天有 1 次查看(给予或接受),我决定在这里发布我的解决方案,希望它可以帮助某人:

function form2Json(str)
{
    "use strict";
    var obj,i,pt,keys,j,ev;
    if (typeof form2Json.br !== 'function')
    {
        form2Json.br = function(repl)
        {
            if (repl.indexOf(']') !== -1)
            {
                return repl.replace(/\](.+?)(,|$)/g,function($1,$2,$3)
                {
                    return form2Json.br($2+'}'+$3);
                });
            }
            return repl;
        };
    }
    str = '{"'+(str.indexOf('%') !== -1 ? decodeURI(str) : str)+'"}';
    obj = str.replace(/\=/g,'":"').replace(/&/g,'","').replace(/\[/g,'":{"');
    obj = JSON.parse(obj.replace(/\](.+?)(,|$)/g,function($1,$2,$3){ return form2Json.br($2+'}'+$3);}));
    pt = ('&'+str).replace(/(\[|\]|\=)/g,'"$1"').replace(/\]"+/g,']').replace(/&([^\[\=]+?)(\[|\=)/g,'"&["$1]$2');
    pt = (pt + '"').replace(/^"&/,'').split('&');
    for (i=0;i<pt.length;i++)
    {
        ev = obj;
        keys = pt[i].match(/(?!:(\["))([^"]+?)(?=("\]))/g);
        for (j=0;j<keys.length;j++)
        {
            if (!ev.hasOwnProperty(keys[j]))
            {
                if (keys.length > (j + 1))
                {
                    ev[keys[j]] = {};
                }
                else
                {
                    ev[keys[j]] = pt[i].split('=')[1].replace(/"/g,'');
                    break;
                }
            }
            ev = ev[keys[j]];
        }
    }
    return obj;
}

我已经对其进行了测试,数据如下所示(4 级深):

str  = "id=007&name[first]=james&name[last]=bond&name[title]=agent&personalia[occupation]=spy&personalia[strength]=women&personalia[weakness]=women&tools[weapons][close][silent]=garrot&tools[weapons][medium][silent]=pistol_supressed&tools[weapons][medium][loud]=smg&tools[weapons][far][silent]=sniper&tools[movement][slow]=foot&tools[movement][far]=DBS";

它巧妙地返回一个对象,当通过JSON.stringify时,结果如下:

{"id":"007","name":{"title":"agent","first":"james","last":"bond"},"personalia":{"weakness":"women","occupation":"spy","strength":"women"},"tools":{"movement":{"far":"DBS","slow":"foot"},"weapons":{"close":{"silent":"garrot"},"medium":{"silent":"pistol_supressed","loud":"smg"},"far":{"silent":"sniper"}}}}

它通过 JSlint 检查,当忽略空格时, . [^...]并接受++ 总而言之,我认为这是可以接受的。

如果您使用 node 或 browserify,则可以使用qs

var qs = require('qs')
var encodedString = "CorrelationId=1&PickedNumbers%5B%5D=1&PickedNumbers%5B%5D=2&PickedNumbers%5B%5D=3&PickedNumbers%5B%5D=4" 

console.log(qs.parse(encodedString))
// { CorrelationId: '1', PickedNumbers: [ '1', '2', '3', '4' ] }

以下代码应该可以解决问题:

var str = 'CorrelationId=1&PickedNumbers%5B%5D=1&PickedNumbers%5B%5D=2&PickedNumbers%5B%5D=3&PickedNumbers%5B%5D=4';
var keyValuePairs = str.split('&');
var json = {};
for(var i=0,len = keyValuePairs.length,tmp,key,value;i <len;i++) {
    tmp = keyValuePairs[i].split('=');
    key = decodeURIComponent(tmp[0]);
    value = decodeURIComponent(tmp[1]);
    if(key.search(/\[\]$/) != -1) {
        tmp = key.replace(/\[\]$/,'');
        json[tmp] = json[tmp] || [];
        json[tmp].push(value);
    }
    else {
        json[key] = value;
    }
}

这是一种纯 JavaScript 方法。 JavaScript 框架也可能会帮助你解决这个问题。 编辑:只是为了踢球,我也加入了字典解析。 参见第二个例子。

function decodeFormParams(params) {
  var pairs = params.split('&'),
      result = {};

  for (var i = 0; i < pairs.length; i++) {
    var pair = pairs[i].split('='),
        key = decodeURIComponent(pair[0]),
        value = decodeURIComponent(pair[1]),
        isArray = /\[\]$/.test(key),
        dictMatch = key.match(/^(.+)\[([^\]]+)\]$/);

    if (dictMatch) {
      key = dictMatch[1];
      var subkey = dictMatch[2];

      result[key] = result[key] || {};
      result[key][subkey] = value;
    } else if (isArray) {
      key = key.substring(0, key.length-2);
      result[key] = result[key] || [];
      result[key].push(value);
    } else {
      result[key] = value;
    }
  }

  return result;
}

decodeFormParams("CorrelationId=1&PickedNumbers%5B%5D=1&PickedNumbers%5B%5D=2&PickedNumbers%5B%5D=3&PickedNumbers%5B%5D=4");
// => {"CorrelationId":"1","PickedNumbers":["1","2","3","4"]}

decodeFormParams("a%5Bb%5D=c&a%5Bd%5D=e");
// => {"a":{"b":"c","d":"e"}}

2022 年的更新答案,在浏览器和节点中均有效。 使用URLSearchParams class。

注意:参数名称PickedNumbers%5B%5D将变为文字字符串PickedNumbers[] 您无需对括号进行编码即可使其成为数组

    const paramsStr = 'CorrelationId=1&PickedNumbers%5B%5D=1&PickedNumbers%5B%5D=2&PickedNumbers%5B%5D=3&PickedNumbers%5B%5D=4';
    const params = new URLSearchParams(paramsStr);
    //access a specific param
    console.log(params.get('PickedNumbers[]')); // '4'
    console.log(params.getAll('PickedNumbers[]')); // ['1','2','3','4']
     const o = Object.fromEntries(Array.from(params.keys()).map(k => [k, params.getAll(k).length===1 ? params.get(k) : params.getAll(k)]));
    console.log(JSON.stringify(o)); //full object

试试这个->

// convert string to object
str = 'a=6&id=99';
var arr = str.split('&');
var obj = {};
for(var i = 0; i < arr.length; i++) {
    var bits = arr[i].split('=');
    obj[bits[0]] = bits[1];
}
//alert(obj.a);
//alert(obj.id);

// convert object back to string
str = '';
for(key in obj) {
    str += key + '=' + obj[key] + '&';
}
str = str.slice(0, str.length - 1); 
alert(str);

或者使用这个(JQuery) http://api.jquery.com/jQuery.param/

你需要 jQuery.param 的反面。 选项之一是http://benalman.com/code/projects/jquery-bbq/examples/deparam/

单线:

let s = 'a=1&b=2&c=3';

Object.fromEntries(
  s.split('&')
   .map(s => s.split('='))
   .map(pair => pair.map(decodeURIComponent)))

// -> {a: "1", b: "2", c: "3"}

如果您希望将重复参数表示为数组:

let s = 'a=1&b=2&c[]=3&c[]=4&c[]=5&c[]=6';

s
  .split('&')
  .map(s => s.split('='))
  .map(pair => pair.map(decodeURIComponent))
  .reduce((memo, [key, value]) => { 
    if (!(key in memo)) { memo[key] = value; } 
    else { 
      if (!(memo[key] instanceof Array)) 
        memo[key] = [memo[key], value]; 
        else 
        memo[key].push(value); 
      } 
    return memo; 
}, {})

// -> {"a":"1","b":"2","c[]":["3","4","5","6"]}
var jsonMessage = "{\"".concat(message.replace("&", "\",\"").replace("=", "\":\"")).concat("\"}");

在 typescript,为我工作:
在object个ParsedQs中使用qs.parse进行改造。
使用 as unknow 隐式类型 unknow 和强制转换为字符串之前。
使用 JSON.parse 将字符串转换为 object。
Joi使用验证很有用。

const payload = JSON.parse(JSON.stringify(qs.parse(request.body) as unknown as string));

有效载荷(卷曲):

--data-urlencode 'notification=123-456123' \
--data-urlencode 'test=123456' \
--data-urlencode 'ajieoajeoa=Lorem ipsum'

结果:

{
  notification: '123-456123',
  test: '123456',
  ajieoajeoa: 'Lorem ipsum'
}
public static void Main()

{

string str ="RESULT=0&PNREF=A10AABBF8DF2&RESPMSG=Approved&AUTHCODE=668PNI&PREFPSMSG=没有触发规则&POSTFPSMSG=没有触发规则";

    var sr = str.Replace("&", "=");

    string[] sp = sr.Split('=');

    var spl = sp.Length;

    int n = 1;

    var ss = "{";

    for (var k = 0; k < spl; k++)
    {
        if (n % 2 == 0)
        {
            if (n == spl)
            {
                ss += '"' + sp[k] + '"';
            }
            else
            {
                ss += '"' + sp[k] + '"' + ",";
            }
        }
        else
        {
            ss += '"' + sp[k] + '"' + ":";
        }
        n++;
    }
    ss += "}";
    Console.WriteLine(ss);
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM