首页 > 解决方案 > 反序列化查询字符串

问题描述

如何使用查询字符串(反)序列化嵌套字典?我查看了有关如何序列化嵌套对象的其他帖子,但我找不到在反序列化时保留原始字典层次结构/布局的便捷方法。

假设我有以下输入:

const params = {
  id: 1,
  filters: {
    price: {
      min: 101,
      max: 300
    }
  },
  sorters: {
    sortBy: 'price',
    order: 'desc'
  }
}

如何使用查询字符串来回转换?

我可以使用 jquery 将其转换为查询字符串$.param,但是当我尝试将其转换回原始字符串时,params它是不正确的:

Object.fromEntries(new URLSearchParams($.param(params)))

输出:

{
  "id": "1",
  "filters[price][min]": "101",
  "filters[price][max]": "300",
  "sorters[sortBy]": "price",
  "sorters[order]": "desc"
}

标签: javascript

解决方案


正如聊天中所讨论的那样 - 似乎您希望能够在客户端和服务器上使用相同的查询条件对象图表示(这是合理的) - 好消息是因为您的对象图具有一致的设计您可以编写一个简单的函数,将图形序列化为更简洁的 URI 查询字符串表示,而无需冗余参数名称前缀或浪费大括号/冒号/引号空间...

总结一下:

  • 对象的唯一可变部分paramsfilters:子对象。idsorters部分有一个固定的布局 - 这意味着有一个filters[]部分是不必要的。

所以这:

const params = {
  id: 1,
  filters: {
    price: {
      min: 101,
      max: 300
    }
  },
  sorters: {
    sortBy: 'price',
    order: 'desc'
  }
}

可以序列化为:

id=1&price_min=101&price_max=300&sortBy=price&dir=desc

下面是一些逻辑,可以将这样的查询字符串反序列化回params您最初拥有的对象:

const queryObject = {
    id: null,
    filter: {},
    sorters: {}
};

const qs = new URLSearchParams( "id=1&price_min=101&price_max=300&sortBy=price&dir=desc" );

for(const [key, value] of qs) {
    if( key === 'id' ) queryObject.id = value;
    else if( key === 'sortBy' ) queryObject.sorters.sortBy = value;
    else if( key === 'dir' ) queryObject.sorters.order = value;
    else {
        if( key.endsWith("_min") || key.endsWith("_max") ) {
            const name = key.substring(0, key.indexof("_"));
            if( !name in queryObject.filters ) {
                queryObject.filters[name] = {};
            }
            if( key.endsWith("_min") ) {
                queryObject.filters[name].min = value;
            } else {
                queryObject.filters[name].max = value;
            }
        }
        else {
            queryObject.filters[key] = value;
        }
    }
}

序列化paramsURLSearchParams也很简单:

const qs = new URLSearchParams();
if( 'id' in params ) qs.set('id', params['id']);
if( 'sortBy' in params.sorters ) qs.set('sortBy', params.sorters.sortBy);
if( 'order' in params.sorters ) qs.set('dir', params.sorters.order);

for( const key of params.filters ) {
    if( typeof(params.filters[key] === 'object') {
        qs.set(key + '_min') = params.filters[key].min;
        qs.set(key + '_max') = params.filters[key].max;
    }
    else {
        qs.set(key) = params.filters[key];
    }
}

推荐阅读