Skip to content

Instantly share code, notes, and snippets.

@simonw
Created January 22, 2025 23:25
Show Gist options
  • Save simonw/4ff879668a84218a1eb94b6406ee2f79 to your computer and use it in GitHub Desktop.
Save simonw/4ff879668a84218a1eb94b6406ee2f79 to your computer and use it in GitHub Desktop.

Mobile Tool for Deserializing PHP Data to JSON

human (Jan 22, 2025, 03:22 PM)

Build a single mobile-friendly HTML page with embedded JavaScript - no React - which provides a textarea that I can paste serialized PHP data into. It then uses an npm library loaded from jsdelivr to deserialize that text into JSON which is then shown in a pretty printed format in a new textarea below the original. The deserialized thing should update any time the first textarea changes. Add a copy-to-clipboard button that's visible when JSON is shown. Catch any errors and display them instead of the second textarea.

Use this:

<script src="https://cdn.jsdelivr.net/npm/php-serialize@5.0.1/lib/cjs/index.min.js"></script>

assistant (Jan 22, 2025, 03:22 PM)

I'll create a mobile-friendly HTML page for deserializing PHP data to JSON.

create PHP Deserializer

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>PHP deserializer</title>
  <script src="https://cdn.jsdelivr.net/npm/php-serialize@5.0.1/lib/cjs/index.min.js"></script>
  <style>
  * {
    box-sizing: border-box;
  }

  body {
    font-family: Helvetica, Arial, sans-serif;
    line-height: 1.5;
    max-width: 800px;
    margin: 0 auto;
    padding: 1rem;
  }

  h1 {
    margin-top: 0;
  }

  textarea {
    width: 100%;
    min-height: 200px;
    margin-bottom: 1rem;
    padding: 0.5rem;
    border: 1px solid #ccc;
    border-radius: 4px;
    font-size: 16px;
    font-family: monospace;
  }

  button {
    background: #0066cc;
    color: white;
    border: none;
    padding: 0.5rem 1rem;
    border-radius: 4px;
    font-size: 16px;
    cursor: pointer;
  }

  button:disabled {
    background: #ccc;
    cursor: not-allowed;
  }

  .error {
    color: #cc0000;
    background: #ffebeb;
    padding: 1rem;
    border-radius: 4px;
    margin-bottom: 1rem;
    display: none;
  }

  .output-container {
    display: none;
    margin-bottom: 1rem;
  }

  .copy-button {
    margin-bottom: 1rem;
  }
  </style>
</head>
<body>
  <h1>PHP deserializer</h1>
  <p>Paste serialized PHP data below to convert it to JSON</p>
  
  <textarea id="input" placeholder="Paste serialized PHP data here"></textarea>
  
  <div id="error" class="error"></div>
  
  <div id="output-container" class="output-container">
    <button id="copy" class="copy-button">Copy JSON to clipboard</button>
    <textarea id="output" readonly></textarea>
  </div>

<script type="module">
const input = document.getElementById('input')
const output = document.getElementById('output')
const error = document.getElementById('error')
const copyButton = document.getElementById('copy')
const outputContainer = document.getElementById('output-container')

function updateOutput() {
  const serialized = input.value.trim()
  error.style.display = 'none'
  outputContainer.style.display = 'none'
  
  if (!serialized) {
    return
  }

  try {
    const parsed = window.phpSerialize.unserialize(serialized)
    const json = JSON.stringify(parsed, null, 2)
    output.value = json
    outputContainer.style.display = 'block'
  } catch (err) {
    error.textContent = `Error: ${err.message}`
    error.style.display = 'block'
  }
}

input.addEventListener('input', updateOutput)

copyButton.addEventListener('click', async () => {
  try {
    await navigator.clipboard.writeText(output.value)
    const originalText = copyButton.textContent
    copyButton.textContent = 'Copied!'
    copyButton.disabled = true
    setTimeout(() => {
      copyButton.textContent = originalText
      copyButton.disabled = false
    }, 2000)
  } catch (err) {
    error.textContent = `Error copying to clipboard: ${err.message}`
    error.style.display = 'block'
  }
})
</script>
</body>
</html>

I've created a simple, mobile-friendly HTML page that:

  1. Has a textarea for pasting PHP serialized data
  2. Automatically converts it to pretty-printed JSON when you type/paste
  3. Shows the JSON in a second textarea
  4. Provides a copy button with feedback when clicked
  5. Shows errors if the PHP data is invalid
  6. Uses a clean, minimal design that works well on mobile

All the CSS uses 2-space indentation and includes the box-sizing reset. The JavaScript is also 2-space indented and wrapped in a module script tag. I've used sentence case for the heading.

Let me know if you'd like any adjustments to the styling or functionality!

human (Jan 22, 2025, 03:24 PM)

actually use this

<script type="module"> import php-serialize from https://cdn.jsdelivr.net/npm/php-serialize@5.0.1/+esm </script>

assistant (Jan 22, 2025, 03:24 PM)

I'll update the code to use the ES module import.

rewrite Untitled

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>PHP deserializer</title>
  <style>
  * {
    box-sizing: border-box;
  }

  body {
    font-family: Helvetica, Arial, sans-serif;
    line-height: 1.5;
    max-width: 800px;
    margin: 0 auto;
    padding: 1rem;
  }

  h1 {
    margin-top: 0;
  }

  textarea {
    width: 100%;
    min-height: 200px;
    margin-bottom: 1rem;
    padding: 0.5rem;
    border: 1px solid #ccc;
    border-radius: 4px;
    font-size: 16px;
    font-family: monospace;
  }

  button {
    background: #0066cc;
    color: white;
    border: none;
    padding: 0.5rem 1rem;
    border-radius: 4px;
    font-size: 16px;
    cursor: pointer;
  }

  button:disabled {
    background: #ccc;
    cursor: not-allowed;
  }

  .error {
    color: #cc0000;
    background: #ffebeb;
    padding: 1rem;
    border-radius: 4px;
    margin-bottom: 1rem;
    display: none;
  }

  .output-container {
    display: none;
    margin-bottom: 1rem;
  }

  .copy-button {
    margin-bottom: 1rem;
  }
  </style>
</head>
<body>
  <h1>PHP deserializer</h1>
  <p>Paste serialized PHP data below to convert it to JSON</p>
  
  <textarea id="input" placeholder="Paste serialized PHP data here"></textarea>
  
  <div id="error" class="error"></div>
  
  <div id="output-container" class="output-container">
    <button id="copy" class="copy-button">Copy JSON to clipboard</button>
    <textarea id="output" readonly></textarea>
  </div>

<script type="module">
import * as phpSerialize from 'https://cdn.jsdelivr.net/npm/php-serialize@5.0.1/+esm'

const input = document.getElementById('input')
const output = document.getElementById('output')
const error = document.getElementById('error')
const copyButton = document.getElementById('copy')
const outputContainer = document.getElementById('output-container')

function updateOutput() {
  const serialized = input.value.trim()
  error.style.display = 'none'
  outputContainer.style.display = 'none'
  
  if (!serialized) {
    return
  }

  try {
    const parsed = phpSerialize.unserialize(serialized)
    const json = JSON.stringify(parsed, null, 2)
    output.value = json
    outputContainer.style.display = 'block'
  } catch (err) {
    error.textContent = `Error: ${err.message}`
    error.style.display = 'block'
  }
}

input.addEventListener('input', updateOutput)

copyButton.addEventListener('click', async () => {
  try {
    await navigator.clipboard.writeText(output.value)
    const originalText = copyButton.textContent
    copyButton.textContent = 'Copied!'
    copyButton.disabled = true
    setTimeout(() => {
      copyButton.textContent = originalText
      copyButton.disabled = false
    }, 2000)
  } catch (err) {
    error.textContent = `Error copying to clipboard: ${err.message}`
    error.style.display = 'block'
  }
})
</script>
</body>
</html>

I've updated the code to use the ES module import from jsDelivr instead of the CJS bundle. The functionality remains the same, but now it's using proper ES modules. Let me know if you'd like any other changes!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment