JSON to Query String
What is a Query String?
A Query String is a part of a URL that contains data in key-value pairs, typically used to pass parameters to web servers. It starts with a question mark (?
) and uses ampersands (&
) to separate multiple parameters.
Format: ?key1=value1&key2=value2&key3=value3
Example: https://api.example.com/users?name=John&age=30&active=true
Understanding the Conversion
Converting JSON to Query String transforms structured data objects into flat URL parameters. This is essential for GET requests, search filters, pagination, and many web APIs that expect parameters in the URL.
JSON vs Query String
Aspect | JSON | Query String |
---|---|---|
Structure | Hierarchical, nested objects | Flat key-value pairs |
Data Types | Multiple types (string, number, boolean, array, object, null) | All values are strings |
Usage | Data storage, APIs, configuration | URL parameters, GET requests |
Format | {"name": "John", "age": 30} | name=John&age=30 |
Encoding | UTF-8 strings | URL-encoded strings |
Why Convert JSON to Query String?
1. GET Request Parameters
Send data through URL for API requests:
// JSON data
{
"search": "javascript",
"category": "programming",
"sort": "date",
"limit": 10
}
// Query String for GET request
// GET /api/posts?search=javascript&category=programming&sort=date&limit=10
2. Search and Filtering
Create shareable URLs with search parameters:
// Search filters
{
"query": "laptop",
"priceMin": 500,
"priceMax": 1500,
"brand": "Apple",
"inStock": true
}
// Shareable URL
// https://store.com/search?query=laptop&priceMin=500&priceMax=1500&brand=Apple&inStock=true
3. Form Submission
Convert form data for URL-based submission:
// Form data
{
"name": "John Doe",
"email": "[email protected]",
"newsletter": true,
"interests": ["tech", "sports"]
}
// Query String
// name=John%20Doe&email=john%40example.com&newsletter=true&interests=tech&interests=sports
4. State Management
Store application state in URL for bookmarking and sharing:
// Application state
{
"tab": "profile",
"userId": 123,
"page": 2,
"view": "grid"
}
// URL with state
// https://app.com/dashboard?tab=profile&userId=123&page=2&view=grid
Conversion Rules
1. Basic Data Types
Strings
// JSON
{"name": "John Doe", "city": "New York"}
// Query String
name=John%20Doe&city=New%20York
Numbers
// JSON
{"age": 30, "price": 29.99}
// Query String
age=30&price=29.99
Booleans
// JSON
{"active": true, "verified": false}
// Query String
active=true&verified=false
Null Values
// JSON
{"optional": null}
// Query String (options)
// Option 1: Skip null values
// (empty - no parameter)
// Option 2: Include as empty
optional=
// Option 3: Include as string
optional=null
2. Arrays
Arrays can be handled in several ways:
Repeated Parameters (Recommended)
// JSON
{"colors": ["red", "blue", "green"]}
// Query String
colors=red&colors=blue&colors=green
Comma-Separated Values
// JSON
{"tags": ["javascript", "programming", "web"]}
// Query String
tags=javascript,programming,web
Indexed Parameters
// JSON
{"items": ["apple", "banana", "orange"]}
// Query String
items[0]=apple&items[1]=banana&items[2]=orange
3. Nested Objects
Objects need to be flattened using various strategies:
Dot Notation
// JSON
{
"user": {
"name": "John",
"address": {
"city": "New York",
"zip": "10001"
}
}
}
// Query String
user.name=John&user.address.city=New%20York&user.address.zip=10001
Bracket Notation
// JSON
{
"filter": {
"price": {"min": 100, "max": 500},
"category": "electronics"
}
}
// Query String
filter[price][min]=100&filter[price][max]=500&filter[category]=electronics
4. URL Encoding
Special characters must be URL-encoded:
// JSON
{
"email": "[email protected]",
"message": "Hello & welcome!",
"url": "https://example.com/path?param=value"
}
// Query String (URL-encoded)
email=user%40example.com&message=Hello%20%26%20welcome%21&url=https%3A//example.com/path%3Fparam%3Dvalue
Conversion Examples
Example 1: Simple API Query
JSON Input:
{
"search": "web development",
"category": "tutorials",
"language": "javascript",
"level": "beginner",
"free": true,
"page": 1,
"limit": 20
}
Query String Output:
search=web%20development&category=tutorials&language=javascript&level=beginner&free=true&page=1&limit=20
Full URL:
https://api.courses.com/search?search=web%20development&category=tutorials&language=javascript&level=beginner&free=true&page=1&limit=20
Example 2: E-commerce Product Filter
JSON Input:
{
"query": "laptop",
"filters": {
"price": {
"min": 500,
"max": 2000
},
"brand": ["Apple", "Dell", "HP"],
"features": {
"ssd": true,
"touchscreen": false,
"weight": {"max": 2.5}
},
"rating": 4
},
"sort": "price_asc",
"page": 2
}
Query String Output (Dot Notation):
query=laptop&filters.price.min=500&filters.price.max=2000&filters.brand=Apple&filters.brand=Dell&filters.brand=HP&filters.features.ssd=true&filters.features.touchscreen=false&filters.features.weight.max=2.5&filters.rating=4&sort=price_asc&page=2
Query String Output (Bracket Notation):
query=laptop&filters[price][min]=500&filters[price][max]=2000&filters[brand]=Apple&filters[brand]=Dell&filters[brand]=HP&filters[features][ssd]=true&filters[features][touchscreen]=false&filters[features][weight][max]=2.5&filters[rating]=4&sort=price_asc&page=2
Example 3: User Registration Form
JSON Input:
{
"personalInfo": {
"firstName": "John",
"lastName": "Doe",
"email": "[email protected]",
"phone": "+1-555-123-4567"
},
"preferences": {
"newsletter": true,
"notifications": {
"email": true,
"sms": false,
"push": true
},
"interests": ["technology", "sports", "travel"]
},
"terms": true,
"referralCode": null
}
Query String Output:
personalInfo.firstName=John&personalInfo.lastName=Doe&personalInfo.email=john.doe%40email.com&personalInfo.phone=%2B1-555-123-4567&preferences.newsletter=true&preferences.notifications.email=true&preferences.notifications.sms=false&preferences.notifications.push=true&preferences.interests=technology&preferences.interests=sports&preferences.interests=travel&terms=true
Example 4: Analytics Tracking Parameters
JSON Input:
{
"event": "page_view",
"properties": {
"page": "/products/laptop-123",
"referrer": "https://google.com/search?q=best+laptop",
"user": {
"id": "user_456",
"segment": "premium"
},
"device": {
"type": "desktop",
"os": "Windows 10",
"browser": "Chrome"
}
},
"timestamp": "2024-01-15T10:30:00Z",
"sessionId": "session_789"
}
Query String Output:
event=page_view&properties.page=%2Fproducts%2Flaptop-123&properties.referrer=https%3A%2F%2Fgoogle.com%2Fsearch%3Fq%3Dbest%2Blaptop&properties.user.id=user_456&properties.user.segment=premium&properties.device.type=desktop&properties.device.os=Windows%2010&properties.device.browser=Chrome×tamp=2024-01-15T10%3A30%3A00Z&sessionId=session_789
Conversion Strategies
1. Flat Conversion (Simple)
Only handle primitive values, skip nested objects:
// JSON
{
"name": "John",
"age": 30,
"address": {"city": "NYC"}, // Skipped
"tags": ["a", "b"] // Skipped
}
// Query String
name=John&age=30
2. Shallow Flatten
Convert first-level objects only:
// JSON
{
"user": {"name": "John", "age": 30},
"settings": {"theme": "dark"}
}
// Query String
user.name=John&user.age=30&settings.theme=dark
3. Deep Flatten
Convert all nested levels:
// JSON
{
"a": {
"b": {
"c": {
"d": "value"
}
}
}
}
// Query String
a.b.c.d=value
Handling Special Cases
1. Empty Values
// JSON
{
"emptyString": "",
"emptyArray": [],
"emptyObject": {},
"nullValue": null
}
// Query String Options:
// Include empty values
emptyString=&emptyArray=&emptyObject=
// Skip empty values
// (no parameters)
// Convert to special markers
emptyArray=__EMPTY_ARRAY__&emptyObject=__EMPTY_OBJECT__
2. Duplicate Keys
// JSON with array
{"color": ["red", "blue"]}
// Query String (duplicate keys)
color=red&color=blue
// Alternative (comma-separated)
color=red,blue
3. Reserved Characters
// JSON
{
"query": "search term with spaces",
"url": "https://example.com?param=value",
"special": "chars: !@#$%^&*()"
}
// Query String (properly encoded)
query=search%20term%20with%20spaces&url=https%3A%2F%2Fexample.com%3Fparam%3Dvalue&special=chars%3A%20%21%40%23%24%25%5E%26%2A%28%29
Implementation Examples
JavaScript
// Simple flat conversion
function jsonToQueryString(obj) {
const params = new URLSearchParams();
for (const [key, value] of Object.entries(obj)) {
if (value !== null && value !== undefined) {
if (Array.isArray(value)) {
value.forEach(item => params.append(key, item));
} else {
params.append(key, value);
}
}
}
return params.toString();
}
// Usage
const data = {
name: "John Doe",
age: 30,
colors: ["red", "blue"]
};
console.log(jsonToQueryString(data));
// Output: name=John+Doe&age=30&colors=red&colors=blue
JavaScript with Nested Objects
function flattenObject(obj, prefix = '') {
const flattened = {};
for (const [key, value] of Object.entries(obj)) {
const newKey = prefix ? `${prefix}.${key}` : key;
if (value === null || value === undefined) {
continue; // Skip null/undefined values
} else if (Array.isArray(value)) {
value.forEach((item, index) => {
if (typeof item === 'object') {
Object.assign(flattened, flattenObject(item, `${newKey}[${index}]`));
} else {
flattened[newKey] = flattened[newKey] || [];
if (!Array.isArray(flattened[newKey])) {
flattened[newKey] = [flattened[newKey]];
}
flattened[newKey].push(item);
}
});
} else if (typeof value === 'object') {
Object.assign(flattened, flattenObject(value, newKey));
} else {
flattened[newKey] = value;
}
}
return flattened;
}
function jsonToQueryString(obj) {
const flattened = flattenObject(obj);
const params = new URLSearchParams();
for (const [key, value] of Object.entries(flattened)) {
if (Array.isArray(value)) {
value.forEach(item => params.append(key, item));
} else {
params.append(key, value);
}
}
return params.toString();
}
Python
import urllib.parse
def json_to_query_string(data, prefix=''):
"""Convert JSON/dict to query string"""
params = []
for key, value in data.items():
param_key = f"{prefix}.{key}" if prefix else key
if value is None:
continue
elif isinstance(value, list):
for item in value:
params.append(f"{param_key}={urllib.parse.quote(str(item))}")
elif isinstance(value, dict):
params.extend(json_to_query_string(value, param_key))
else:
params.append(f"{param_key}={urllib.parse.quote(str(value))}")
return params
# Usage
data = {
"name": "John Doe",
"filters": {
"price": {"min": 100, "max": 500}
},
"tags": ["tech", "programming"]
}
query_parts = json_to_query_string(data)
query_string = "&".join(query_parts)
print(query_string)
Best Practices
1. Choose Consistent Array Format
// Stick to one format throughout your application
// Option A: Repeated parameters (recommended for most cases)
tags=javascript&tags=python&tags=web
// Option B: Comma-separated (for simple arrays)
tags=javascript,python,web
// Option C: Indexed (for ordered arrays)
tags[0]=javascript&tags[1]=python&tags[2]=web
2. Handle URL Length Limits
// Check query string length (URLs have limits ~2048 chars)
function createQueryString(data) {
const queryString = jsonToQueryString(data);
if (queryString.length > 2000) {
console.warn('Query string may be too long for some browsers');
// Consider using POST request instead
}
return queryString;
}
3. Sanitize Input Data
function sanitizeValue(value) {
if (typeof value === 'string') {
// Remove potentially harmful characters
return value.replace(/[<>'"]/g, '');
}
return value;
}
function safeJsonToQueryString(obj) {
const sanitized = {};
for (const [key, value] of Object.entries(obj)) {
sanitized[key] = sanitizeValue(value);
}
return jsonToQueryString(sanitized);
}
4. Consider Server Expectations
// Different servers expect different formats
const configs = {
php: {
arrayFormat: 'brackets', // tags[]=a&tags[]=b
objectFormat: 'brackets' // user[name]=John
},
rails: {
arrayFormat: 'repeat', // tags=a&tags=b
objectFormat: 'brackets' // user[name]=John
},
express: {
arrayFormat: 'repeat', // tags=a&tags=b
objectFormat: 'dot' // user.name=John
}
};
Common Use Cases
1. API Requests
// Building API request URLs
const apiParams = {
endpoint: 'users',
filters: {
active: true,
role: 'admin'
},
pagination: {
page: 1,
limit: 20
}
};
const queryString = jsonToQueryString(apiParams);
const apiUrl = `https://api.example.com/users?${queryString}`;
2. Search Forms
// Converting search form to URL
const searchForm = {
q: 'javascript tutorial',
category: 'programming',
level: 'beginner',
free: true
};
const searchUrl = `https://courses.com/search?${jsonToQueryString(searchForm)}`;
3. State Persistence
// Saving application state in URL
const appState = {
currentTab: 'dashboard',
selectedItems: [1, 2, 3],
filters: {
dateRange: '30days',
status: 'active'
}
};
window.history.pushState({}, '', `?${jsonToQueryString(appState)}`);
4. Analytics Tracking
// Building tracking URLs
const trackingData = {
event: 'purchase',
value: 99.99,
currency: 'USD',
userId: 'user123'
};
const trackingUrl = `https://analytics.com/track?${jsonToQueryString(trackingData)}`;
Limitations and Considerations
1. Data Type Loss
- All values become strings in query strings
- Need to parse back to original types when receiving
2. URL Length Limits
- Browsers limit URL length (~2048 characters)
- Consider POST requests for large data
3. Encoding Issues
- Special characters need proper URL encoding
- Unicode characters may cause issues
4. Security Concerns
- Sensitive data visible in URLs
- URLs are logged in server logs and browser history
Conclusion
Converting JSON to Query String is essential for:
- GET request parameters in web APIs
- Shareable URLs with embedded state
- Form submissions via URL encoding
- Search and filtering interfaces
Key considerations:
- Choose appropriate nesting strategy (dot notation vs brackets)
- Handle arrays consistently throughout your application
- Properly encode special characters to avoid URL issues
- Consider URL length limits for large datasets
- Be mindful of security when exposing data in URLs
The conversion process transforms structured JSON data into flat key-value pairs suitable for URL transmission while maintaining data integrity and ensuring compatibility with web standards.