JSON verkleinen

Plak JSON en krijg dezelfde gegevens terug op één regel, zonder witruimte tussen de elementen. Er wordt geparseerd en opnieuw geschreven en niet met tekens geschoven, dus wat eruit komt is hetzelfde document — inclusief de spaties die binnen tekstwaarden staan, want die horen bij de gegevens. Het gebeurt allemaal in je browser.

Resultaat

Het antwoord verschijnt hier terwijl je typt.

  • Waar het draait

    Er wordt niets geüpload, want er is geen bestand — het wordt in deze pagina uitgerekend.

  • Geen wachtrij, geen account

    Het antwoordt zo snel als je machine kan, en vraagt nooit wie je bent.

  • Zo vaak als je wilt

    Er wordt niets geteld en niets begrensd — nog eens antwoorden kost ons niets.

Hoe het werkt

  1. Plak de JSON.
  2. Bepaal of je de sleutels alfabetisch wilt sorteren, handig als je twee documenten gaat vergelijken.
  3. Kopieer de regel. Er is niets geüpload.

Geparseerd, niet weggeknipt

Verkleinen betekent hier: het document lezen en zonder witruimte opnieuw schrijven. Het goedkope alternatief — alle spaties en regeleindes weghalen — sloopt elke tekstwaarde waar een spatie in staat, en dat is vrijwel elk document met een naam of een adres erin.

Het gevolg is dat een geslaagde verkleining tegelijk een geldigheidscontrole is. Komt er iets uit, dan was het document geldig. Komt er niets uit, dan was het dat niet, en dan geeft de controlepagina de regel en de kolom waar het vastloopt.

De winst wordt in bytes gemeten

Wat je bespaart is de witruimte tussen de elementen: de inspringing, de regeleindes en de spatie na een dubbele punt. Bij een opgemaakt document met twee spaties inspringing scheelt dat vaak twintig tot dertig procent van de tekens, en bij diep genest JSON meer.

Het getal dat telt is echter niet het aantal tekens maar het aantal bytes, en die twee lopen uiteen zodra er niet-ASCII in staat. Een naam met een trema kost twee bytes per zo’n letter, dus een veld met een grens van 255 bytes past minder tekst dan het aantal tekens doet vermoeden. Dat is precies waar een verkleind document meestal in moet passen.

Wat het toevoegt als er al Gzip is

Over de lijn is de winst klein. Gzip en Brotli comprimeren herhaalde witruimte uitstekend, dus een verkleind document dat gecomprimeerd wordt verstuurd, scheelt vaak maar een paar procent ten opzichte van het opgemaakte. Wie minificeert om de bandbreedte, doet het meestal voor niets.

Waar het wel telt is overal waar niet gecomprimeerd wordt: een waarde in een omgevingsvariabele, een kolom met een lengtegrens, een logregel die op één regel moet passen, een QR-code. Daar telt de onverpakte omvang rechtstreeks, en daar is dit hulpmiddel voor bedoeld.

Waar het sorteren van sleutels voor dient

Een JSON-object heeft geen vastgelegde volgorde, dus twee diensten kunnen dezelfde gegevens met de sleutels op andere plekken teruggeven. Alfabetisch sorteren maakt van een tekstvergelijking tussen twee antwoorden een zinnige vergelijking.

Het is daarmee vooral een hulpmiddel voor diffs en contracttests. De volgorde van arrays blijft altijd staan, want daar is de volgorde deel van het gegeven — een hulpmiddel dat ook die zou sorteren, levert documenten op die netjes vergelijken en iets anders betekenen.

Sorteren is niet canoniseren

Wie een handtekening over JSON berekent, heeft meer nodig dan gesorteerde sleutels. Een canonieke vorm legt ook vast hoe getallen worden geschreven, welke tekens als `\uXXXX` worden ontsnapt en hoe Unicode wordt genormaliseerd — precies de dingen waarin twee implementaties stilletjes verschillen.

Daarvoor bestaat JSON Canonicalization Scheme, RFC 8785. Sorteren zoals het hier gebeurt komt daar dichtbij en is het niet, en dat verschil is genoeg om een handtekening te laten mislukken. Bouw je iets met handtekeningen over JSON, gebruik dan een implementatie van die specificatie en niet deze pagina.

Grote gehele getallen overleven de rit niet

JSON schrijft getallen als tekst en JavaScript leest ze als drijvende komma met dubbele precisie. Gehele getallen boven ongeveer negen biljard verliezen cijfers, en omdat de uitkomst nog altijd een geldig getal is, valt het niemand op.

Bij verkleinen doet dat extra pijn, want het resultaat gaat meestal ergens in dat het letterlijk bewaart: een omgevingsvariabele, een kolom, een sjabloon. Het beschadigde getal reist dan mee en wordt pas ergens verderop een record dat niet gevonden wordt. Er wordt gemeld wanneer het gebeurt; de oplossing ligt bij wie die identifiers uitgeeft, en die horen als tekst te reizen.

Eén regel is niets voor een repository

Geminificeerde JSON in een bestand onder versiebeheer maakt van elke wijziging één gewijzigde regel. Reviewen wordt daarmee onmogelijk, de diff wordt alles of niets, en een merge-conflict raakt het hele document in plaats van het veld waar het over ging.

De verdeling die werkt is: opgemaakt in de repository, verkleind bij het uitleveren. De stap ertussen hoort een buildproces te zetten. Zet je het verkleinde document zelf in de repository, dan lever je de leesbaarheid in op de enige plek waar die iets waard is.

Het regeleinde aan het eind

De uitvoer hier eindigt zonder regeleinde, want het is één waarde en geen tekstbestand. Editors zetten er bij het opslaan vaak vanzelf een achter, en dat is op Unix ook de conventie voor bestanden.

Die byte telt op twee plekken. Hij verandert de hash van het document, dus twee «identieke» bestanden krijgen verschillende checksums, en hij kan een veld met een strikte lengtegrens net over de rand duwen. Vergelijk je uitkomsten en scheelt het precies één byte, dan is dit vrijwel altijd de reden.

Waar één regel echt nodig is

De aanleidingen zijn tamelijk vast: een configuratiewaarde in een omgevingsvariabele, waar een regeleinde het inlezen breekt; een kolom in een database met een maximum; een gestructureerde logregel, waar elke regel één gebeurtenis is; een bericht in een wachtrij met een limiet per bericht.

In al die gevallen is het formaat een eis en geen optimalisatie. Dat is het onderscheid dat de moeite waard is: verkleinen om bandbreedte te sparen is meestal zinloos naast Gzip, en verkleinen omdat het doel geen regeleindes toelaat, is gewoon de vorm die daar hoort.

Waarom lege velden blijven staan

Er is geen optie om velden met `null` of met een lege tekst weg te laten, en dat is een besluit. Een ontbrekend veld en een veld met `null` zijn niet hetzelfde: het eerste zegt «hier staat niets over», het tweede zegt «dit is uitdrukkelijk leeg», en veel API’s behandelen ze verschillend.

Zo’n optie zou dus geen witruimte weghalen maar gegevens, onder de noemer van verkleinen. Wie velden wil weglaten, moet dat doen op de plek waar het document wordt samengesteld, waar bekend is wat het onderscheid betekent — en niet in een hulpmiddel dat alleen naar de vorm kijkt.

Verkleinen is geen comprimeren

De twee worden door elkaar gehaald en doen iets anders. Verkleinen verandert de weergave: wat eruit komt is nog steeds JSON en elke parser leest het zonder voorbereiding. Comprimeren verandert de bytes in iets dat eerst uitgepakt moet worden voordat er iemand iets mee kan.

Dat verschil bepaalt welke van de twee je nodig hebt. Vraagt een systeem om «compacte JSON» in een veld, dan bedoelt het verkleind, want het gaat het daarna lezen. Gaat het over verkeer over de lijn, dan is comprimeren het antwoord en levert verkleinen er nauwelijks iets bovenop.

De AVG bij een payload van één regel

Wat hier verkleind wordt is meestal een echt document: een klantrecord, een bestelling, de body van een webhook. Omdat er op de pagina zelf wordt geparseerd en herschreven, is er geen verstrekking aan ons en dus ook geen verwerking in onze opdracht van die inhoud.

Daar komt een praktisch punt bij dat bij verkleinen extra telt: het resultaat gaat vaak in een configuratiebestand of een omgevingsvariabele, en daarmee ergens waar het lang blijft staan. Wat er in gaat verdient dus een blik, en die blik kun je hier werpen zonder het document eerst ergens heen te sturen.

JSON verkleinen: veelgestelde vragen

Blijven de spaties binnen mijn tekstwaarden staan?

Ja. Er wordt geparseerd en opnieuw geschreven, dus alleen de witruimte tussen elementen verdwijnt. Wat binnen een tekstwaarde staat hoort bij de gegevens en blijft ongemoeid.

Heeft het zin als mijn API al Gzip gebruikt?

Over de lijn nauwelijks: compressie ruimt herhaalde witruimte uitstekend op. Het telt waar er niet gecomprimeerd wordt — een omgevingsvariabele, een kolom met een lengtegrens, een logregel, een QR-code.

Waarom verandert mijn lange identifier?

Omdat JavaScript getallen als drijvende komma met dubbele precisie leest en gehele getallen boven ongeveer negen biljard cijfers verliezen. Zulke waarden horen als tekst in JSON te staan.

Waarom wordt mijn document met commentaar geweigerd?

Omdat JSON geen commentaar kent, en ook geen komma achter het laatste element. Dat zijn gewoontes uit JavaScript. Heb je commentaar nodig, dan is YAML, TOML of JSON5 het formaat.

Verlaat de JSON mijn machine?

Nee. Het parseren en schrijven gebeurt op deze pagina. Dat telt, want wat hier binnenkomt is meestal een echt document: een klantrecord, een bestelling, de body van een webhook.

Andere hulpmiddelen