当其中一个值中存在空格而不更改该值时,我无法将查询字符串解析为数组:
示例搜索参数:
filters=%7B"value"%3A"test%20ing"%2C"type"%3A"search"%7D%20%7B"dataIndex"%3A"plan"%2C"value"%3A"5b61c72879f4503bfa9e729b"%2C"type"%3A"oid"%7D
分析结果:(字符串)
{"value":"test ing","type":"search"} {"dataIndex":"plan","value":"5b61c72879f4503bfa9e729b","type":"oid"}
所需结果:数组
[
{"value":"test ing","type":"search"},
{"dataIndex":"plan","value":"5b61c72879f4503bfa9e729b","type":"oid"}
]
尝试的方法
["{"value":"test", "ing","type":"search"}", "{"dataIndex":"plan","value":"5b61c72879f4503bfa9e729b","type":"oid"}"]
我在每个space
之间都有一个object
,并希望跳到split
,但是当使用这种方法时,如果存在空格,它将分裂value
见上文。
为达到预期效果,建议的方法是什么?
答案 0 :(得分:0)
已解析的字符串不是有效的JSON-您必须在} {
之间手动插入逗号以使其生效,然后您可以在{{1}内JSON.parse
} s:
[]
也就是说,如果可能的话,最好修复生成此输入的代码,这样就不必进行这样的修改,而您只需这样做
const input = 'filters=%7B"value"%3A"test%20ing"%2C"type"%3A"search"%7D%20%7B"dataIndex"%3A"plan"%2C"value"%3A"5b61c72879f4503bfa9e729b"%2C"type"%3A"oid"%7D';
const malformedFilters = new URLSearchParams(input).get('filters');
const fixedFilters = malformedFilters.replace('} {', '}, {');
const arr = JSON.parse('[' + fixedFilters + ']');
console.log(arr);
答案 1 :(得分:0)
嗯...由于您拥有搜索栏和过滤器,因此可以将所有内容组合到一个JSON array
中,并将搜索和单个过滤器限制在自己的object
中。
工作示例:https://codesandbox.io/s/lx8n5x4w4z
components / SearchForm.js
import filter from "lodash/filter";
import map from "lodash/map";
import React, { Component } from "react";
import ParsedURI from "./parsedURI";
import FilterField from "./filterField";
import SearchField from "./searchField";
// initial form state
const initialState = {
fieldsCount: 1,
search: { value: "", type: "search" },
filters: [{ id: 1, dataIndex: "", value: "", type: "" }]
};
export default class SearchForm extends Component {
state = { ...initialState };
// handles search input changes
handleSearchChange = ({ target: { name, value } }) => {
this.setState(prevState => ({
search: { ...prevState.search, [name]: value }
}));
};
// handles all filter changes (select, select and input) by their id
handleFilterChange = ({ target: { id, name, value } }) => {
this.setState(prevState => ({
filters: map(
prevState.filters,
item =>
parseInt(id, 10) === item.id
? { ...item, [name]: value }
: { ...item }
)
}));
};
// adds a new field to filters and updates a field counter
addField = () => {
this.setState(prevState => ({
filters: [
...this.state.filters,
{
id: this.state.fieldsCount + 1,
dataIndex: "",
value: "",
type: ""
}
],
fieldsCount: this.state.fieldsCount + 1
}));
};
// removes selected filter field by id
deleteField = id => {
this.setState(prevState => ({
filters: filter(this.state.filters, field => field.id !== id)
}));
};
// resets form to initial state and updates the URL
handleReset = () =>
this.setState(
{
encodedJSON: "",
filtersJSON: "",
...initialState
},
() => this.props.history.replace("/search/")
);
// handles form submission
handleSubmit = e => {
e.preventDefault();
const { search, filters } = this.state;
const arr = [];
// flatten search and filter options into a single array
arr.push({ ...search }, ...filters);
// convert that array to a JSON array
const filtersJSON = JSON.stringify(arr);
// convert JSON array to an encodedURI
const encodedJSON = `filters=${encodeURI(filtersJSON)}`;
// set to state and push to URL
this.setState(
{
encodedJSON,
filtersJSON: arr,
...initialState
},
() => this.props.history.push(`/search/filters?${encodedJSON}`)
);
};
render = () => (
<div style={{ padding: "5px 20px" }}>
<form onSubmit={this.handleSubmit}>
<SearchField
value={this.state.search.value}
handleSearchChange={this.handleSearchChange}
/>
<p>Select a filter, option, and input a value:</p>
{map(this.state.filters, ({ id, ...rest }) => (
<FilterField
key={id}
id={id}
deleteField={this.deleteField}
filtersLength={this.state.filters.length}
handleFilterChange={this.handleFilterChange}
{...rest}
/>
))}
<br />
<button
type="button"
style={{ marginRight: 20, marginBottom: 20 }}
className="uk-button uk-button-primary"
onClick={this.addField}
>
Add Filter
</button>
<br />
<div style={{ marginTop: 40 }}>
<button
type="button"
style={{ marginRight: 20, marginBottom: 20, float: "left" }}
className="uk-button uk-button-danger"
onClick={this.handleReset}
>
Reset Form
</button>
<button className="uk-button uk-button-secondary" type="submit">
Submit
</button>
</div>
</form>
{this.state.encodedJSON && this.state.filtersJSON ? (
<ParsedURI
encodedJSON={this.state.encodedJSON}
filtersJSON={this.state.filtersJSON}
/>
) : null}
</div>
);
}
编码的URI字符串示例:
%5B%7B%22value%22:%22Test%20ing%22,%22type%22:%22search%22%7D,%7B%22id%22:1,%22dataIndex%22:%22topic%22,%22value%22:%22React%20Local%20State%22,%22type%22:%22name%22%7D,%7B%22id%22:2,%22dataIndex%22:%22subcategory%22,%22value%22:%22123456789%22,%22type%22:%22oid%22%7D%5D
示例解码的URL字符串JSON.stringify(filtersJSON, null, 4)
:
[
{
"value": "Test ing",
"type": "search"
},
{
"id": 1,
"dataIndex": "topic",
"value": "React Local State",
"type": "name"
},
{
"id": 2,
"dataIndex": "subcategory",
"value": "123456789",
"type": "oid"
}
]
答案 2 :(得分:0)
通过使用这种方法能够弄清所需的内容:
编码URL助手:
const encodeUrl = filters => filters.reduce((str, filter) => `${str}${URI.encode(JSON.stringify(filter))}&&`, '')
格式查询助手:
const formatQuery = query => compact(query.split('&&') || [])
解析查询:
const filters = URI.decode(this.props.location.search).replace('?filters=', '')
API(将查询过滤器传递给api服务):
${PLANS_API_ENDPOINT}?filters=[${formatQuery(query)}]