Installation:
composer require egeloen/json-builder
Add to composer.json under require if not using Composer globally.
Basic Usage:
use Ivory\Json\JsonBuilder;
$builder = new JsonBuilder();
$json = $builder->build(['key' => 'value']);
echo $json; // Outputs: {"key":"value"}
First Use Case:
return response()->json($builder->build([
'status' => 'success',
'data' => $user->toArray()
]));
Ivory\Json\JsonBuilder and its methods (build(), setEscaping(), etc.).setEscaping(false) for raw output).$builder->build($object)).Building JSON from Arrays/Objects:
// Arrays
$builder->build(['users' => [1, 2, 3]]);
// Objects (via PropertyAccess)
$builder->build((object)['name' => 'John']);
Escaping Control:
$builder->setEscaping(false);
$json = $builder->build('<script>alert("XSS")</script>');
$builder->setEscaping(true); // Default
Integration with Laravel:
return response()->json($builder->build($data), 200, [], JSON_PRETTY_PRINT);
JsonBuilder to the container for reuse:
$this->app->singleton(JsonBuilder::class, function ($app) {
return new JsonBuilder();
});
Nested Data Handling:
$builder->build([
'user' => (object)['posts' => ['title' => 'Hello']]
]);
// Output: {"user":{"posts":{"title":"Hello"}}}
Custom Escaping Logic:
Extend JsonBuilder to add custom escaping rules:
class CustomJsonBuilder extends JsonBuilder {
public function build($data) {
$this->setEscaping(function ($value) {
return str_replace('"', '\\"', $value);
});
return parent::build($data);
}
}
Batch Processing: Useful for generating multiple JSON responses:
$builder = new JsonBuilder();
$responses = collect($items)->map(fn ($item) => $builder->build($item));
Validation Integration: Combine with Laravel Validation for structured JSON:
$validated = $request->validate(['name' => 'required|string']);
return response()->json($builder->build($validated));
Escaping Overhead:
setEscaping(false)) bypasses security checks. Use only for trusted data.$builder->setEscaping(false);
$json = $builder->build($userInput); // Risk of XSS if $userInput is untrusted.
Circular References:
json_encode() as fallback:
try {
$json = $builder->build($data);
} catch (\RuntimeException $e) {
$json = json_encode($data);
}
PropertyAccess Limitations:
PropertyAccess configuration. Ensure your objects are accessible:
$propertyAccessor = PropertyAccess::createPropertyAccessorBuilder()
->enableMagicCall()
->getPropertyAccessor();
$builder->setPropertyAccessor($propertyAccessor);
Inspect Raw Data:
Use var_dump() or dd() to verify input structure before building JSON:
dd($builder->getData()); // Check data before serialization.
Error Handling:
Wrap build() in try-catch for graceful fallbacks:
try {
$json = $builder->build($data);
} catch (\Exception $e) {
Log::error("JSON build failed: " . $e->getMessage());
return response()->json(['error' => 'Invalid data'], 500);
}
Performance:
JsonBuilder instances (e.g., as a singleton) to avoid reinitialization overhead.Custom Serializers:
Implement Ivory\Json\Serializer\SerializerInterface to handle custom types:
class DateTimeSerializer implements SerializerInterface {
public function serialize($value) {
return $value->format('Y-m-d');
}
}
$builder->addSerializer(new DateTimeSerializer());
Event Listeners:
Extend JsonBuilder to trigger events (e.g., pre/post-build hooks):
$builder->addListener(function ($data) {
$data['timestamp'] = now()->toIso8601String();
return $data;
});
Configuration:
$builder = new JsonBuilder();
$builder->setEscaping(config('app.json_escaping', true));
$this->app->singleton(JsonBuilder::class, fn() => $builder);
How can I help you explore Laravel packages today?