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 @@ - diff --git a/resources/views/api.blade.php b/resources/views/api.blade.php new file mode 100644 index 0000000..47c34b0 --- /dev/null +++ b/resources/views/api.blade.php @@ -0,0 +1,291 @@ +@extends('layouts.app') + +@section('title', 'JSON API Documentation') + +@push('styles') + +@endpush + +@section('content') +
+

JSON API Documentation

+

Programmatic access to JSON validation and formatting tools

+
+ +
+
+

Getting Started

+

Our JSON API provides endpoints for validating, formatting, and comparing JSON documents. All endpoints accept and return JSON data.

+ +

Base URL

+
+ {{ url('/api/json') }} +
+ +

Authentication

+

Currently, the API is open and does not require authentication. However, rate limiting may be implemented in the future.

+
+
+ +
+
+ POST + /validate +
+
+

Validate JSON

+

Validates a JSON document and returns the parsed data if valid.

+ +

Request

+
+
{
+    "json": "{\"name\":\"John\",\"age\":30}"
+}
+
+ +

Response (Success)

+
+
{
+    "status": "success",
+    "message": "Valid JSON",
+    "data": {
+        "name": "John",
+        "age": 30
+    }
+}
+
+ +

Response (Error)

+
+
{
+    "status": "error",
+    "message": "Invalid JSON",
+    "error": "Syntax error"
+}
+
+
+
+ +
+
+ POST + /validate-schema +
+
+

Validate JSON Against Schema

+

Validates a JSON document against a JSON Schema.

+ +

Request

+
+
{
+    "json": "{\"name\":\"John\",\"age\":30}",
+    "schema": "{
+        \"type\":\"object\",
+        \"properties\":{
+            \"name\":{\"type\":\"string\"},
+            \"age\":{\"type\":\"number\"}
+        },
+        \"required\":[\"name\",\"age\"]
+    }"
+}
+
+ +

Response (Success)

+
+
{
+    "status": "success",
+    "message": "JSON is valid according to the schema",
+    "data": {
+        "name": "John",
+        "age": 30
+    }
+}
+
+ +

Response (Error)

+
+
{
+    "status": "error",
+    "message": "JSON does not match schema",
+    "errors": [
+        {
+            "instancePath": "/age",
+            "message": "must be a number"
+        }
+    ]
+}
+
+
+
+ +
+
+ POST + /format +
+
+

Format JSON

+

Formats a JSON document with specified indentation.

+ +

Request

+
+
{
+    "json": "{\"name\":\"John\",\"age\":30}",
+    "indent": 2
+}
+
+ +

Response (Success)

+
+
{
+    "status": "success",
+    "message": "JSON formatted successfully",
+    "data": "{
+  \"name\": \"John\",
+  \"age\": 30
+}"
+}
+
+
+
+ +
+
+ POST + /compare +
+
+

Compare JSON Documents

+

Compares two JSON documents and returns the differences.

+ +

Request

+
+
{
+    "json1": "{\"name\":\"John\",\"age\":30}",
+    "json2": "{\"name\":\"John\",\"age\":31}"
+}
+
+ +

Response (Success)

+
+
{
+    "status": "success",
+    "message": "JSON comparison completed",
+    "data": {
+        "are_equal": false,
+        "differences": [
+            {
+                "path": ["age"],
+                "old_value": 30,
+                "new_value": 31
+            }
+        ]
+    }
+}
+
+
+
+ +
+
+

Example Usage

+

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}"}'
+
+
+
+@endsection \ No newline at end of file diff --git a/resources/views/jsoncompare.blade.php b/resources/views/jsoncompare.blade.php new file mode 100644 index 0000000..be711d3 --- /dev/null +++ b/resources/views/jsoncompare.blade.php @@ -0,0 +1,251 @@ +@extends('layouts.app') + +@section('title', 'JSON Compare - Free Online JSON Diff Tool') + +@push('styles') + + +@endpush + +@section('content') +
+

JSON Compare Tool

+

Compare and visualize differences between two JSON documents

+
+ +
+
+
+ +

Side-by-Side Diff

+

View differences between two JSON documents in a clear, visual format

+
+
+
+
+ +

Color-Coded

+

Easily identify additions, deletions, and modifications with color coding

+
+
+
+
+ +

Collapsible

+

Navigate large JSON documents with collapsible nodes

+
+
+
+ +
+
+
+
+ + +
+
+ + +
+
+
+ + +
+
+
+ +
+
+

Comparison Result

+
+
+
+
+ +
+

About JSON Compare Tool

+
+
+

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.

+ +

Key Features:

+
    +
  • Side-by-side JSON comparison
  • +
  • Color-coded differences (green for additions, red for deletions, yellow for modifications)
  • +
  • Collapsible nodes for easy navigation
  • +
  • Dark and light mode support
  • +
  • Mobile-friendly interface
  • +
+ +

How to Use:

+
    +
  1. Enter or paste your first JSON document in the left textarea
  2. +
  3. Enter or paste your second JSON document in the right textarea
  4. +
  5. Click the "Compare JSON" button to see the differences
  6. +
  7. Use the collapsible nodes to navigate through the differences
  8. +
+
+
+
+@endsection + +@push('scripts') + + + +@endpush \ No newline at end of file diff --git a/resources/views/jsonlint.blade.php b/resources/views/jsonlint.blade.php new file mode 100644 index 0000000..dc9380a --- /dev/null +++ b/resources/views/jsonlint.blade.php @@ -0,0 +1,577 @@ +@extends('layouts.app') + +@section('title', 'JSON Lint - Free Online JSON Validator and Formatter') + +@push('styles') + + + + +@endpush + +@section('content') +
+

JSON Lint Tool

+

Validate, format, and beautify your JSON data with our powerful online tool

+
+ +
+
+
+ +

Validate JSON

+

Quickly check if your JSON data is valid and well-formed

+
+
+
+
+ +

Format JSON

+

Automatically format and beautify your JSON for better readability

+
+
+
+
+ +

Tree View

+

Visualize your JSON structure with an interactive tree view

+
+
+
+ +
+
+
+

JSON Editor

+
+
+ + +
+
+ + + + +
+
+
+ + +
+
+

Formatted JSON

+ + + +
+
+
+
+
+

+            
+
+
+
+ +
+

About JSON Lint Tool

+
+
+

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.

+ +

Key Features:

+
    +
  • Real-time JSON validation
  • +
  • Automatic JSON formatting and beautification
  • +
  • Interactive tree view for easy navigation
  • +
  • Dark and light mode support
  • +
  • Mobile-friendly interface
  • +
+ +

What is JSON?

+

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.

+
+
+
+@endsection + +@push('scripts') + + + +@endpush \ No newline at end of file diff --git a/resources/views/jsonschema.blade.php b/resources/views/jsonschema.blade.php new file mode 100644 index 0000000..7cfdc8e --- /dev/null +++ b/resources/views/jsonschema.blade.php @@ -0,0 +1,356 @@ +@extends('layouts.app') + +@section('title', 'JSON Schema Validator - Free Online JSON Schema Validation Tool') + +@push('styles') + + +@endpush + +@section('content') +
+

JSON Schema Validator

+

Validate your JSON data against a JSON Schema

+
+ +
+
+
+ +

Schema Validation

+

Validate your JSON data against a JSON Schema specification

+
+
+
+
+ +

Interactive Editor

+

Edit both JSON and Schema in a user-friendly interface

+
+
+
+
+ +

Real-time Feedback

+

Get instant validation results with detailed error messages

+
+
+
+ +
+
+
+
+ + +
+
+ + +
+
+
+ + +
+
+
+ +
+
+

Validation Result

+
+ + + +
+
+
+
+
+

+            
+
+
+
+ +
+

About JSON Schema Validation

+
+
+

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.

+ +

Key Features:

+
    +
  • Validate JSON data against JSON Schema specifications
  • +
  • Interactive JSON and Schema editors
  • +
  • Detailed validation error messages
  • +
  • Tree view and raw JSON view options
  • +
  • Dark and light mode support
  • +
+ +

How to Use:

+
    +
  1. Enter or paste your JSON data in the left textarea
  2. +
  3. Enter or paste your JSON Schema in the right textarea
  4. +
  5. Click the "Validate" button to check if your JSON conforms to the schema
  6. +
  7. View the validation results and any error messages
  8. +
+ +

Example Schema:

+
{
+    "type": "object",
+    "properties": {
+        "name": { "type": "string" },
+        "age": { "type": "number", "minimum": 0 },
+        "email": { "type": "string", "format": "email" }
+    },
+    "required": ["name", "age", "email"]
+}
+
+
+
+@endsection + +@push('scripts') + + + + +@endpush \ No newline at end of file diff --git a/resources/views/jsontemplates.blade.php b/resources/views/jsontemplates.blade.php new file mode 100644 index 0000000..717c9c6 --- /dev/null +++ b/resources/views/jsontemplates.blade.php @@ -0,0 +1,384 @@ +@extends('layouts.app') + +@section('title', 'JSON Templates - Common JSON Formats and Examples') + +@push('styles') + + +@endpush + +@section('content') +
+

JSON Templates

+

Common JSON formats and examples for various use cases

+
+ +
+

API Responses

+
+
+
+
+ +

REST API Response

+

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 Response

+

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"
+                            }
+                        }
+                    ]
+                }
+            ]
+        }
+    }
+}
+
+
+ +
+
+
+
+ +
+

Configuration Files

+
+
+
+
+ +

Application Config

+

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
+    }
+}
+
+
+ +
+
+
+
+
+ +

Package.json

+

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"
+}
+
+
+ +
+
+
+
+ +
+

Data Structures

+
+
+
+
+ +

User Profile

+

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

+

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"
+}
+
+
+ +
+
+
+
+@endsection + +@push('scripts') + +@endpush \ No newline at end of file diff --git a/resources/views/layouts/app.blade.php b/resources/views/layouts/app.blade.php index 0a471a4..db7b78d 100644 --- a/resources/views/layouts/app.blade.php +++ b/resources/views/layouts/app.blade.php @@ -1,36 +1,145 @@ - + - - - + + + + + + @yield('title', 'JSON Tools') + + + @stack('styles') + - -
- @include('layouts.navigation') + + - - @isset($header) -
-
- {{ $header }} -
-
- @endisset - - -
- {{ $slot }} -
+
+ @yield('content')
+ + + + @stack('scripts') diff --git a/routes/api.php b/routes/api.php new file mode 100644 index 0000000..e9b4ee9 --- /dev/null +++ b/routes/api.php @@ -0,0 +1,35 @@ +get('/user', function (Request $request) { + return $request->user(); +}); + +// JSON Validation API Routes +Route::prefix('json')->group(function () { + // Validate JSON + Route::post('/validate', [JsonApiController::class, 'validateJson']); + + // Validate JSON against schema + Route::post('/validate-schema', [JsonApiController::class, 'validateSchema']); + + // Format JSON + Route::post('/format', [JsonApiController::class, 'formatJson']); + + // Compare JSON documents + Route::post('/compare', [JsonApiController::class, 'compareJson']); +}); \ No newline at end of file diff --git a/routes/web.php b/routes/web.php index 74bb7ca..d703283 100644 --- a/routes/web.php +++ b/routes/web.php @@ -4,13 +4,37 @@ use App\Http\Controllers\ProfileController; use Illuminate\Support\Facades\Route; Route::get('/', function () { - return view('welcome'); + return view('jsonlint'); +}); + +Route::get('/compare', function () { + return view('jsoncompare'); }); Route::get('/dashboard', function () { return view('dashboard'); })->middleware(['auth', 'verified'])->name('dashboard'); +Route::get('/jsonlint', function () { + return view('jsonlint'); +}); + +Route::get('/jsoncompare', function () { + return view('jsoncompare'); +}); + +Route::get('/jsonschema', function () { + return view('jsonschema'); +}); + +Route::get('/jsontemplates', function () { + return view('jsontemplates'); +}); + +Route::get('/api', function () { + return view('api'); +})->name('api'); + Route::middleware('auth')->group(function () { Route::get('/profile', [ProfileController::class, 'edit'])->name('profile.edit'); Route::patch('/profile', [ProfileController::class, 'update'])->name('profile.update');