Separate query syntax from data before decoding
The question mark starts the query component of a URL, ampersands separate name-value pairs, and an equals sign separates a parameter name from its value. Those characters can also be ordinary data, but only after they are percent-encoded inside the component that owns them.
VetaTool accepts a complete URL, a relative URL containing a question mark, or a raw query string. It extracts the query portion first and then lets URLSearchParams decode each key and value. That ordering matters because decoding an encoded ampersand too early would turn data back into a separator before the parameter boundaries are known.
Raw ampersand creates another parameter
?note=fish&chips&format=jsonEncoded ampersand stays inside one value
?note=fish%26chips&format=jsonTreat plus signs and percent escapes as form-style encoding
URLSearchParams follows application/x-www-form-urlencoded rules rather than treating every plus sign as a literal plus character. A raw + decodes to a space, while %2B decodes to +. Percent-encoded UTF-8 sequences are decoded in keys and values as part of the same parsing step.
Build mode uses URLSearchParams.toString(), so spaces are serialized as + and characters that need escaping are percent-encoded. If the receiving system distinguishes a literal plus from a space, encode the plus as %2B before treating the text as a query value.
Space versus literal plus
?term=C%2B%2B+guideParsed value
{
"term": "C++ guide"
}Preserve repeated keys, empty values, and flags
Repeated parameters are not automatically duplicates to discard. APIs commonly use repeated keys for filters, tags, or multi-select values. VetaTool records the first value as a string and converts that key to an ordered JSON array when another value with the same name appears.
An explicit empty value such as name= remains an empty string. A flag-style parameter such as debug is also parsed by URLSearchParams as the key debug with an empty-string value. A missing key is different because it never appears in the parsed object at all.
Repeated and empty parameters
?tag=json&tag=tools&debug&name=Parsed JSON
{
"tag": [
"json",
"tools"
],
"debug": "",
"name": ""
}Build repeated parameters from JSON arrays deliberately
Build mode requires a top-level JSON object. A primitive value becomes one query parameter, while an array of primitive values becomes the same key repeated once per array item in its original order. Nested objects are rejected because bracket notation, dotted keys, JSON text, and other nested-query conventions are application-specific rather than interchangeable.
null is emitted as an explicit empty value, just like an empty string, while an empty array emits no parameter pairs because there are no array items to append. Booleans and finite safe numbers are converted to their string forms. Unsafe integers are rejected before serialization so large identifiers are not silently rounded by JavaScript number handling.
Build input
{
"tag": ["json", "tools"],
"debug": true,
"empty": null,
"skip": []
}Built query string
tag=json&tag=tools&debug=true&empty=Encode embedded URLs and ignore fragments at the right boundary
A fragment beginning with # is outside the query component, so VetaTool ignores it when parsing a complete or relative URL. Text inside the fragment should not be treated as another query parameter even when it contains equals signs or ampersands.
An embedded URL is the opposite case: its inner ?, &, and = characters belong to data inside an outer parameter value. Encode that nested URL as one component before appending it, otherwise the outer parser can mistake the inner ampersands for additional top-level parameters.
Encoded redirect URL
?next=https%3A%2F%2Fexample.com%2Fsearch%3Fq%3Djson%26page%3D2Use a repeatable query-string diagnosis workflow
Start with the smallest URL or raw query that still shows the unexpected behavior. Mark the outer separators first, then inspect percent escapes, repeated names, empty values, and embedded components. Only after the parsed key-value model is clear should you decide whether the receiving application expects arrays, flags, bracket notation, or another convention.
- Separate the query component from the path and fragment before interpreting parameters.
- Check raw &, =, +, and % characters to decide which are syntax and which are intended data.
- Preserve repeated keys and empty values while comparing the parsed result with the API contract.
- When building, use only the primitive or primitive-array representation that the receiver documents.
- Encode embedded URLs or other structured values as one component before placing them inside an outer query string.