<?php
require_once __DIR__ . '/../config.php';
require_once __DIR__ . '/../includes/functions.php';

$page_title   = 'JSON Formatter & Validator – Format and Validate JSON';
$page_desc    = 'Free JSON formatter and validator: format, minify and validate JSON data instantly in your browser – on ipcheck.tools.';
$page_current = 'json-formatter';

require_once __DIR__ . '/header.php';
?>

<div class="hero">
  <div class="hero-label">Tool</div>
  <div class="hero-title">JSON Formatter &amp; Validator</div>
  <div class="hero-sub">Format, validate and minify JSON data</div>
</div>

<div class="wrap">

  <div class="ad-slot"><ins class="adsbygoogle" style="display:block" data-ad-client="ca-pub-8287576653347400" data-ad-slot="2715725452" data-ad-format="auto" data-full-width-responsive="true"></ins><script>(adsbygoogle = window.adsbygoogle || []).push({});</script></div>

  <div style="display:flex; gap:8px; flex-wrap:wrap;">
    <button onclick="formatJSON()"   class="btn btn-primary"  style="font-size:13px;"><i class="ti ti-code"></i> Format</button>
    <button onclick="minifyJSON()"   class="btn btn-ghost"    style="font-size:13px;"><i class="ti ti-minimize"></i> Minify</button>
    <button onclick="validateJSON()" class="btn btn-ghost"    style="font-size:13px;"><i class="ti ti-check"></i> Validate</button>
    <button onclick="clearAll()"     class="btn btn-ghost"    style="font-size:13px; margin-left:auto;"><i class="ti ti-trash"></i> Clear</button>
  </div>

  <div id="status-box" style="display:none;" class="alert"></div>

  <div class="grid2">
    <div class="card">
      <div class="card-title"><i class="ti ti-code"></i> Input
        <span style="margin-left:auto;">
          <button onclick="copyInput()" class="copy-btn" style="margin-top:0; font-size:11px; padding:3px 10px;"><i class="ti ti-copy"></i> Copy</button>
        </span>
      </div>
      <textarea id="input-text"
        style="width:100%; background:var(--bg3); border:1px solid #2d3a52; border-radius:7px; padding:12px 14px; font-size:12px; color:var(--text); font-family:var(--font-mono); outline:none; resize:vertical; min-height:300px; line-height:1.5;"
        placeholder='{"name":"Alice","age":30,"city":"London"}'
        oninput="liveValidate()"></textarea>
      <div style="margin-top:8px; display:flex; gap:8px;">
        <span id="input-chars" style="font-size:11px; color:var(--text4);">0 chars</span>
        <span id="input-lines" style="font-size:11px; color:var(--text4);">0 lines</span>
      </div>
    </div>
    <div class="card">
      <div class="card-title"><i class="ti ti-braces"></i> Output
        <span style="margin-left:auto;">
          <button onclick="copyOutput()" class="copy-btn" style="margin-top:0; font-size:11px; padding:3px 10px;"><i class="ti ti-copy"></i> Copy</button>
        </span>
      </div>
      <textarea id="output-text" readonly
        style="width:100%; background:var(--bg3); border:1px solid #1e2a3a; border-radius:7px; padding:12px 14px; font-size:12px; color:var(--blue-dim); font-family:var(--font-mono); outline:none; resize:vertical; min-height:300px; line-height:1.5;"
        placeholder="Formatted JSON appears here..."></textarea>
      <div style="margin-top:8px; display:flex; gap:8px;">
        <span id="output-chars" style="font-size:11px; color:var(--text4);">0 chars</span>
        <span id="output-lines" style="font-size:11px; color:var(--text4);">0 lines</span>
      </div>
    </div>
  </div>

  <div style="display:flex; align-items:center; gap:12px; flex-wrap:wrap;">
    <span style="font-size:12px; color:var(--text3);">Indentation:</span>
    <label style="display:flex; align-items:center; gap:5px; font-size:12px; color:var(--text3); cursor:pointer;"><input type="radio" name="indent" value="2" checked onchange="formatJSON()"> 2 spaces</label>
    <label style="display:flex; align-items:center; gap:5px; font-size:12px; color:var(--text3); cursor:pointer;"><input type="radio" name="indent" value="4" onchange="formatJSON()"> 4 spaces</label>
    <label style="display:flex; align-items:center; gap:5px; font-size:12px; color:var(--text3); cursor:pointer;"><input type="radio" name="indent" value="tab" onchange="formatJSON()"> Tab</label>
  </div>

  <div class="card">
    <div class="card-title"><i class="ti ti-bookmark"></i> Load examples</div>
    <div style="display:flex; gap:8px; flex-wrap:wrap;">
      <button onclick="loadExample('simple')" class="copy-btn" style="margin-top:0;">Simple object</button>
      <button onclick="loadExample('array')"  class="copy-btn" style="margin-top:0;">Array</button>
      <button onclick="loadExample('nested')" class="copy-btn" style="margin-top:0;">Nested</button>
      <button onclick="loadExample('invalid')" class="copy-btn" style="margin-top:0; color:var(--red); border-color:#3a2020;">Invalid JSON</button>
    </div>
  </div>

  <div class="ad-slot"><ins class="adsbygoogle" style="display:block" data-ad-client="ca-pub-8287576653347400" data-ad-slot="2715725452" data-ad-format="auto" data-full-width-responsive="true"></ins><script>(adsbygoogle = window.adsbygoogle || []).push({});</script></div>

  <div class="tools-row">
    <a href="/en/"                   class="tool-btn"><i class="ti ti-home"></i><span>My IP</span></a>
    <a href="/en/json-formatter.php" class="tool-btn current"><i class="ti ti-braces"></i><span>JSON</span></a>
    <a href="/en/base64.php"         class="tool-btn"><i class="ti ti-code"></i><span>Base64</span></a>
    <a href="/en/hash.php"           class="tool-btn"><i class="ti ti-hash"></i><span>Hash</span></a>
    <a href="/en/url-encoder.php"    class="tool-btn"><i class="ti ti-link"></i><span>URL Encoder</span></a>
  </div>

  <div class="seo-box">
    <h2>What is JSON?</h2>
    <p>JSON (JavaScript Object Notation) is a lightweight data interchange format that is easy to read for both humans and machines. It is widely used for APIs, configuration files and data exchange between web services. This tool lets you format JSON data (pretty print), minify it or validate it for syntax errors.</p>
  </div>

<script>
const examples = {
  simple: '{"name":"Alice Smith","age":30,"city":"London","email":"alice@example.com","active":true}',
  array:  '[{"id":1,"name":"Alice","role":"admin"},{"id":2,"name":"Bob","role":"user"},{"id":3,"name":"Charlie","role":"user"}]',
  nested: '{"user":{"name":"Alice","address":{"street":"123 Main St","city":"London"},"hobbies":["coding","reading"],"metadata":{"created":"2024-01-01","verified":true}}}',
  invalid: '{"name":"Alice","age":30,,}'
};

function getIndent() {
  const val = document.querySelector('input[name="indent"]:checked').value;
  return val === 'tab' ? '\t' : parseInt(val);
}

function updateStats() {
  const inp = document.getElementById('input-text').value;
  const out = document.getElementById('output-text').value;
  document.getElementById('input-chars').textContent  = inp.length + ' chars';
  document.getElementById('input-lines').textContent  = inp.split('\n').length + ' lines';
  document.getElementById('output-chars').textContent = out.length + ' chars';
  document.getElementById('output-lines').textContent = out.split('\n').length + ' lines';
}

function showStatus(msg, type) {
  const box  = document.getElementById('status-box');
  box.style.display = 'flex';
  box.className = 'alert alert-' + type;
  box.innerHTML = '<i class="ti ' + (type === 'success' ? 'ti-check' : (type === 'danger' ? 'ti-alert-circle' : 'ti-info-circle')) + '"></i><span>' + msg + '</span>';
}

function liveValidate() {
  const input = document.getElementById('input-text').value.trim();
  updateStats();
  if (!input) { document.getElementById('status-box').style.display = 'none'; return; }
  try { JSON.parse(input); showStatus('Valid JSON', 'success'); }
  catch(e) { showStatus('Invalid JSON: ' + e.message, 'danger'); }
}

function formatJSON() {
  const input = document.getElementById('input-text').value.trim();
  if (!input) return;
  try {
    document.getElementById('output-text').value = JSON.stringify(JSON.parse(input), null, getIndent());
    showStatus('JSON formatted successfully', 'success');
  } catch(e) { showStatus('Error: ' + e.message, 'danger'); document.getElementById('output-text').value = ''; }
  updateStats();
}

function minifyJSON() {
  const input = document.getElementById('input-text').value.trim();
  if (!input) return;
  try {
    document.getElementById('output-text').value = JSON.stringify(JSON.parse(input));
    showStatus('JSON minified', 'success');
  } catch(e) { showStatus('Error: ' + e.message, 'danger'); }
  updateStats();
}

function validateJSON() {
  const input = document.getElementById('input-text').value.trim();
  if (!input) { showStatus('Please enter JSON', 'info'); return; }
  try {
    const parsed = JSON.parse(input);
    const keys = typeof parsed === 'object' && parsed !== null ? Object.keys(parsed).length : '–';
    showStatus('✓ Valid JSON · ' + (Array.isArray(parsed) ? parsed.length + ' entries' : keys + ' keys'), 'success');
  } catch(e) { showStatus('✗ Invalid JSON: ' + e.message, 'danger'); }
}

function clearAll() {
  document.getElementById('input-text').value  = '';
  document.getElementById('output-text').value = '';
  document.getElementById('status-box').style.display = 'none';
  updateStats();
}

function copyInput()  { const v = document.getElementById('input-text').value;  if (v) navigator.clipboard.writeText(v); }
function copyOutput() { const v = document.getElementById('output-text').value; if (v) { navigator.clipboard.writeText(v); showStatus('Copied to clipboard', 'success'); } }

function loadExample(key) {
  document.getElementById('input-text').value = examples[key];
  if (key !== 'invalid') formatJSON(); else liveValidate();
}
</script>

<?php require_once __DIR__ . '/footer.php'; ?>
