反序列化查询字符串

问题描述

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

假设我有以下输入:

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"
}

解决方法

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

总结:

  • params 对象中唯一的可变参数部分是 filters: 子对象。 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;
        }
    }
}

params 序列化为 URLSearchParams 也很简单:

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];
    }
}

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...