diff --git a/app/Http/Controllers/JsonApiController.php b/app/Http/Controllers/JsonApiController.php
new file mode 100644
index 0000000..c4bd37e
--- /dev/null
+++ b/app/Http/Controllers/JsonApiController.php
@@ -0,0 +1,183 @@
+all(), [
+ 'json' => 'required|json',
+ ]);
+
+ if ($validator->fails()) {
+ return response()->json([
+ 'status' => 'error',
+ 'message' => 'Invalid request',
+ 'errors' => $validator->errors()
+ ], 400);
+ }
+
+ try {
+ $json = json_decode($request->input('json'), true, 512, JSON_THROW_ON_ERROR);
+
+ return response()->json([
+ 'status' => 'success',
+ 'message' => 'Valid JSON',
+ 'data' => $json
+ ]);
+ } catch (\JsonException $e) {
+ return response()->json([
+ 'status' => 'error',
+ 'message' => 'Invalid JSON',
+ 'error' => $e->getMessage()
+ ], 400);
+ }
+ }
+
+ /**
+ * Validate JSON against a schema
+ *
+ * @param Request $request
+ * @return JsonResponse
+ */
+ public function validateSchema(Request $request): JsonResponse
+ {
+ $validator = Validator::make($request->all(), [
+ 'json' => 'required|json',
+ 'schema' => 'required|json',
+ ]);
+
+ if ($validator->fails()) {
+ return response()->json([
+ 'status' => 'error',
+ 'message' => 'Invalid request',
+ 'errors' => $validator->errors()
+ ], 400);
+ }
+
+ try {
+ $json = json_decode($request->input('json'), true, 512, JSON_THROW_ON_ERROR);
+ $schema = json_decode($request->input('schema'), true, 512, JSON_THROW_ON_ERROR);
+
+ // Use Ajv for schema validation
+ $ajv = new \Ajv();
+ $validate = $ajv->compile($schema);
+ $valid = $validate($json);
+
+ if ($valid) {
+ return response()->json([
+ 'status' => 'success',
+ 'message' => 'JSON is valid according to the schema',
+ 'data' => $json
+ ]);
+ }
+
+ return response()->json([
+ 'status' => 'error',
+ 'message' => 'JSON does not match schema',
+ 'errors' => $validate->errors
+ ], 400);
+
+ } catch (\JsonException $e) {
+ return response()->json([
+ 'status' => 'error',
+ 'message' => 'Invalid JSON or schema',
+ 'error' => $e->getMessage()
+ ], 400);
+ }
+ }
+
+ /**
+ * Format JSON
+ *
+ * @param Request $request
+ * @return JsonResponse
+ */
+ public function formatJson(Request $request): JsonResponse
+ {
+ $validator = Validator::make($request->all(), [
+ 'json' => 'required|json',
+ 'indent' => 'integer|min:0|max:8',
+ ]);
+
+ if ($validator->fails()) {
+ return response()->json([
+ 'status' => 'error',
+ 'message' => 'Invalid request',
+ 'errors' => $validator->errors()
+ ], 400);
+ }
+
+ try {
+ $json = json_decode($request->input('json'), true, 512, JSON_THROW_ON_ERROR);
+ $indent = $request->input('indent', 2);
+
+ return response()->json([
+ 'status' => 'success',
+ 'message' => 'JSON formatted successfully',
+ 'data' => json_encode($json, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE, $indent)
+ ]);
+ } catch (\JsonException $e) {
+ return response()->json([
+ 'status' => 'error',
+ 'message' => 'Invalid JSON',
+ 'error' => $e->getMessage()
+ ], 400);
+ }
+ }
+
+ /**
+ * Compare two JSON documents
+ *
+ * @param Request $request
+ * @return JsonResponse
+ */
+ public function compareJson(Request $request): JsonResponse
+ {
+ $validator = Validator::make($request->all(), [
+ 'json1' => 'required|json',
+ 'json2' => 'required|json',
+ ]);
+
+ if ($validator->fails()) {
+ return response()->json([
+ 'status' => 'error',
+ 'message' => 'Invalid request',
+ 'errors' => $validator->errors()
+ ], 400);
+ }
+
+ try {
+ $json1 = json_decode($request->input('json1'), true, 512, JSON_THROW_ON_ERROR);
+ $json2 = json_decode($request->input('json2'), true, 512, JSON_THROW_ON_ERROR);
+
+ $diff = new \Diff($json1, $json2);
+
+ return response()->json([
+ 'status' => 'success',
+ 'message' => 'JSON comparison completed',
+ 'data' => [
+ 'are_equal' => $json1 === $json2,
+ 'differences' => $diff->getDifferences()
+ ]
+ ]);
+ } catch (\JsonException $e) {
+ return response()->json([
+ 'status' => 'error',
+ 'message' => 'Invalid JSON',
+ 'error' => $e->getMessage()
+ ], 400);
+ }
+ }
+}
\ No newline at end of file
diff --git a/composer.json b/composer.json
index 8284202..34595b8 100644
--- a/composer.json
+++ b/composer.json
@@ -76,4 +76,4 @@
},
"minimum-stability": "stable",
"prefer-stable": true
-}
\ No newline at end of file
+}
diff --git a/docker-compose.yml b/docker-compose.yml
new file mode 100644
index 0000000..429f3dd
--- /dev/null
+++ b/docker-compose.yml
@@ -0,0 +1,55 @@
+services:
+ laravel.test:
+ build:
+ context: './vendor/laravel/sail/runtimes/8.4'
+ dockerfile: Dockerfile
+ args:
+ WWWGROUP: '${WWWGROUP}'
+ image: 'sail-8.4/app'
+ extra_hosts:
+ - 'host.docker.internal:host-gateway'
+ ports:
+ - '${APP_PORT:-8082}:80'
+ - '${VITE_PORT:-5173}:${VITE_PORT:-5173}'
+ environment:
+ WWWUSER: '${WWWUSER}'
+ LARAVEL_SAIL: 1
+ XDEBUG_MODE: '${SAIL_XDEBUG_MODE:-off}'
+ XDEBUG_CONFIG: '${SAIL_XDEBUG_CONFIG:-client_host=host.docker.internal}'
+ IGNITION_LOCAL_SITES_PATH: '${PWD}'
+ volumes:
+ - '.:/var/www/html'
+ networks:
+ - sail
+ depends_on:
+ - mysql
+ mysql:
+ image: 'mysql/mysql-server:8.0'
+ ports:
+ - '${FORWARD_DB_PORT:-3309}:3306'
+ environment:
+ MYSQL_ROOT_PASSWORD: '${DB_PASSWORD}'
+ MYSQL_ROOT_HOST: '%'
+ MYSQL_DATABASE: '${DB_DATABASE}'
+ MYSQL_USER: '${DB_USERNAME}'
+ MYSQL_PASSWORD: '${DB_PASSWORD}'
+ MYSQL_ALLOW_EMPTY_PASSWORD: 1
+ volumes:
+ - 'sail-mysql:/var/lib/mysql'
+ - './vendor/laravel/sail/database/mysql/create-testing-database.sh:/docker-entrypoint-initdb.d/10-create-testing-database.sh'
+ networks:
+ - sail
+ healthcheck:
+ test:
+ - CMD
+ - mysqladmin
+ - ping
+ - '-p${DB_PASSWORD}'
+ retries: 3
+ timeout: 5s
+networks:
+ sail:
+ driver: bridge
+volumes:
+ sail-mysql:
+ driver: local
diff --git a/phpunit.xml b/phpunit.xml
index 61c031c..ab193d1 100644
--- a/phpunit.xml
+++ b/phpunit.xml
@@ -22,7 +22,6 @@
Programmatic access to JSON validation and formatting tools
+Our JSON API provides endpoints for validating, formatting, and comparing JSON documents. All endpoints accept and return JSON data.
+ +Currently, the API is open and does not require authentication. However, rate limiting may be implemented in the future.
+Validates a JSON document and returns the parsed data if valid.
+ +{
+ "json": "{\"name\":\"John\",\"age\":30}"
+}
+ {
+ "status": "success",
+ "message": "Valid JSON",
+ "data": {
+ "name": "John",
+ "age": 30
+ }
+}
+ {
+ "status": "error",
+ "message": "Invalid JSON",
+ "error": "Syntax error"
+}
+ Validates a JSON document against a JSON Schema.
+ +{
+ "json": "{\"name\":\"John\",\"age\":30}",
+ "schema": "{
+ \"type\":\"object\",
+ \"properties\":{
+ \"name\":{\"type\":\"string\"},
+ \"age\":{\"type\":\"number\"}
+ },
+ \"required\":[\"name\",\"age\"]
+ }"
+}
+ {
+ "status": "success",
+ "message": "JSON is valid according to the schema",
+ "data": {
+ "name": "John",
+ "age": 30
+ }
+}
+ {
+ "status": "error",
+ "message": "JSON does not match schema",
+ "errors": [
+ {
+ "instancePath": "/age",
+ "message": "must be a number"
+ }
+ ]
+}
+ Formats a JSON document with specified indentation.
+ +{
+ "json": "{\"name\":\"John\",\"age\":30}",
+ "indent": 2
+}
+ {
+ "status": "success",
+ "message": "JSON formatted successfully",
+ "data": "{
+ \"name\": \"John\",
+ \"age\": 30
+}"
+}
+ Compares two JSON documents and returns the differences.
+ +{
+ "json1": "{\"name\":\"John\",\"age\":30}",
+ "json2": "{\"name\":\"John\",\"age\":31}"
+}
+ {
+ "status": "success",
+ "message": "JSON comparison completed",
+ "data": {
+ "are_equal": false,
+ "differences": [
+ {
+ "path": ["age"],
+ "old_value": 30,
+ "new_value": 31
+ }
+ ]
+ }
+}
+ Here's an example of how to use the API with cURL:
+ +# Validate JSON
+curl -X POST {{ url('/api/json/validate') }} \
+ -H "Content-Type: application/json" \
+ -d '{"json":"{\"name\":\"John\",\"age\":30}"}'
+
+# Format JSON
+curl -X POST {{ url('/api/json/format') }} \
+ -H "Content-Type: application/json" \
+ -d '{"json":"{\"name\":\"John\",\"age\":30}","indent":2}'
+
+# Compare JSON
+curl -X POST {{ url('/api/json/compare') }} \
+ -H "Content-Type: application/json" \
+ -d '{"json1":"{\"name\":\"John\",\"age\":30}","json2":"{\"name\":\"John\",\"age\":31}"}'
+ Compare and visualize differences between two JSON documents
+View differences between two JSON documents in a clear, visual format
+Easily identify additions, deletions, and modifications with color coding
+Navigate large JSON documents with collapsible nodes
+Our JSON Compare Tool helps you identify differences between two JSON documents quickly and efficiently. Whether you're comparing API responses, configuration files, or any other JSON data, our tool provides a clear visualization of the changes.
+ +Validate, format, and beautify your JSON data with our powerful online tool
+Quickly check if your JSON data is valid and well-formed
+Automatically format and beautify your JSON for better readability
+Visualize your JSON structure with an interactive tree view
+Our JSON Lint Tool is a free online service that helps developers and data analysts work with JSON data more efficiently. Whether you're validating API responses, debugging JSON configurations, or just need to format your JSON data, our tool provides a simple and intuitive interface to get the job done.
+ +JSON (JavaScript Object Notation) is a lightweight data-interchange format that is easy for humans to read and write and easy for machines to parse and generate. It is widely used for transmitting data between a server and web application, as well as for configuration files and data storage.
+Validate your JSON data against a JSON Schema
+Validate your JSON data against a JSON Schema specification
+Edit both JSON and Schema in a user-friendly interface
+Get instant validation results with detailed error messages
+JSON Schema is a powerful tool for validating the structure of JSON data. It allows you to define the expected format, data types, and constraints for your JSON documents. Our JSON Schema Validator makes it easy to validate your JSON data against a schema specification.
+ +{
+ "type": "object",
+ "properties": {
+ "name": { "type": "string" },
+ "age": { "type": "number", "minimum": 0 },
+ "email": { "type": "string", "format": "email" }
+ },
+ "required": ["name", "age", "email"]
+}
+ Common JSON formats and examples for various use cases
+Standard REST API response with status, data, and pagination
+{
+ "status": "success",
+ "code": 200,
+ "message": "Data retrieved successfully",
+ "data": {
+ "items": [
+ {
+ "id": 1,
+ "name": "Item 1",
+ "description": "Description of item 1"
+ },
+ {
+ "id": 2,
+ "name": "Item 2",
+ "description": "Description of item 2"
+ }
+ ],
+ "pagination": {
+ "total": 100,
+ "per_page": 10,
+ "current_page": 1,
+ "last_page": 10
+ }
+ }
+}
+ GraphQL API response with nested data structure
+{
+ "data": {
+ "user": {
+ "id": "1",
+ "name": "John Doe",
+ "email": "john@example.com",
+ "posts": [
+ {
+ "id": "101",
+ "title": "First Post",
+ "content": "Content of the first post",
+ "comments": [
+ {
+ "id": "1001",
+ "text": "Great post!",
+ "author": {
+ "id": "2",
+ "name": "Jane Smith"
+ }
+ }
+ ]
+ }
+ ]
+ }
+ }
+}
+ Common application configuration settings
+{
+ "app": {
+ "name": "My Application",
+ "version": "1.0.0",
+ "environment": "production",
+ "debug": false
+ },
+ "database": {
+ "host": "localhost",
+ "port": 3306,
+ "name": "mydb",
+ "username": "user",
+ "password": "secret"
+ },
+ "logging": {
+ "level": "info",
+ "file": "app.log",
+ "max_size": "10MB"
+ },
+ "api": {
+ "base_url": "https://api.example.com",
+ "timeout": 30,
+ "retry_attempts": 3
+ }
+}
+ Node.js package configuration
+{
+ "name": "my-package",
+ "version": "1.0.0",
+ "description": "A sample Node.js package",
+ "main": "index.js",
+ "scripts": {
+ "start": "node index.js",
+ "test": "jest",
+ "build": "webpack"
+ },
+ "dependencies": {
+ "express": "^4.17.1",
+ "lodash": "^4.17.21"
+ },
+ "devDependencies": {
+ "jest": "^27.0.6",
+ "webpack": "^5.50.0"
+ },
+ "author": "John Doe",
+ "license": "MIT"
+}
+ User profile data structure
+{
+ "id": "user123",
+ "username": "johndoe",
+ "email": "john@example.com",
+ "profile": {
+ "firstName": "John",
+ "lastName": "Doe",
+ "age": 30,
+ "gender": "male",
+ "location": {
+ "country": "USA",
+ "city": "New York"
+ }
+ },
+ "preferences": {
+ "theme": "dark",
+ "notifications": true,
+ "language": "en"
+ },
+ "createdAt": "2023-01-01T00:00:00Z",
+ "lastLogin": "2023-06-15T14:30:00Z"
+}
+ E-commerce order data structure
+{
+ "orderId": "ORD-2023-001",
+ "customer": {
+ "id": "CUST-001",
+ "name": "John Doe",
+ "email": "john@example.com",
+ "shippingAddress": {
+ "street": "123 Main St",
+ "city": "New York",
+ "state": "NY",
+ "zipCode": "10001",
+ "country": "USA"
+ }
+ },
+ "items": [
+ {
+ "productId": "PROD-001",
+ "name": "Product 1",
+ "quantity": 2,
+ "price": 29.99,
+ "total": 59.98
+ },
+ {
+ "productId": "PROD-002",
+ "name": "Product 2",
+ "quantity": 1,
+ "price": 49.99,
+ "total": 49.99
+ }
+ ],
+ "subtotal": 109.97,
+ "tax": 10.99,
+ "shipping": 5.99,
+ "total": 126.95,
+ "status": "processing",
+ "createdAt": "2023-06-15T10:30:00Z"
+}
+