API’s, open data & integratie

Een beschadigde JSON-sequentie lezen zonder volledigheid te veinzen

De kern

Herstelbaarheid en volledigheid zijn verschillende eigenschappen. Geef een beschadigd record een zichtbare plaats in het resultaat.

Wat past bij jou? Beantwoord 30 korte vragen →

Herstel is een productbeslissing

Een client die meerdere JSON-records ontvangt, moet eerst het afgesproken framingformaat kennen. Een JSON-array, losse documenten per regel en een JSON-tekstsequentie zijn geen onderling verwisselbare bestanden. De vraag hier is hoe je bij een sequentie de bruikbare delen kunt onderzoeken zonder een beschadiging onzichtbaar te maken.

RFC 7464 beschrijft UTF-8 JSON-tekstsequenties en herstel na beschadigde elementen; opeenvolgende RS-bytes betekenen geen lege elementen.[5] De oefening negeert lege stukken tussen separators, ook na een afsluitende RS. Het lokale acceptatiebeleid vereist LF na iedere niet-lege kandidaat en een object met tekstuele id. Dat objectprofiel en die LF-eis vormen niet de volledige parsergrammatica.

Maak een lokale parsefout zichtbaar

  • accepted_ids bevat alleen de objecten die dit lokale profiel doorstaan.
  • gaps bevat lokale rangnummers van niet-lege parsekandidaten, geen betrouwbare bronrecordposities.
  • partial_hold verbiedt in deze oefening de claim dat de export volledig is.
  • framing_ok betekent uitsluitend dat dit framingprofiel geen gat vond; het bewijst geen verwachte recordset.

De letterlijke beschadigde invoer uitvoeren

De bytefixture hieronder zet een RS vóór ieder element. Tussen de intacte objecten met id A en C staat een onvolledig object. De code ontvangt de volledige bytebuffer, maximaal 4096 bytes, en verstuurt niets. Het doel is een zichtbare gatadministratie, niet een bestand repareren door verzonnen inhoud toe te voegen.

Gebruik Kopieer code om alle code exact te kopiëren. Handmatig selecteren kan de laatste regelovergang weglaten.

import json

def recover(raw):
    if type(raw) is not bytes or len(raw) not in range(4097) or (raw and not raw.startswith(b"\x1e")):
        raise ValueError("unsupported sequence envelope")
    accepted, gaps = [], []
    # Consecutive/trailing RS bytes do not create empty sequence elements.
    candidates = (chunk for chunk in raw.split(b"\x1e")[1:] if chunk)
    for number, chunk in enumerate(candidates, 1):
        try:
            if not chunk.endswith(b"\n"):
                raise ValueError("missing final LF under local policy")
            value = json.loads(chunk.decode("utf-8"))
            if type(value) is not dict or type(value.get("id")) is not str:
                raise ValueError("this example requires an object with text id")
        except (ValueError, UnicodeError):
            gaps.append(number)
        else:
            accepted.append(value["id"])
    return {"accepted_ids": accepted, "gaps": gaps,
            "state": "partial_hold" if gaps else "framing_ok"}

# Literal RS bytes surround one broken object and two intact objects.
fixture = b'\x1e{"id":"A"}\n\x1e{"id":\n\x1e{"id":"C"}\n'
result = recover(fixture)
assert result["accepted_ids"] == ["A", "C"] and result["gaps"] == [2]
assert recover(b'\x1e{"id":"A"}')["gaps"] == [1]
assert recover(b'\x1etrue\n')["gaps"] == [1]
assert recover(b'\x1e{"id":1}\n')["gaps"] == [1]
for bad in [b'{"id":"A"}\n', b' ' * 4097]:
    try:
        recover(bad)
    except ValueError:
        pass
    else:
        raise AssertionError("unsupported envelope accepted")
assert recover(b'\x1e\x1e{"id":"A"}\n\x1e')["gaps"] == []
assert recover(b'\x1e\x1e')["gaps"] == []
print(json.dumps({"recovery": result, "additional_gap_cases": 3, "envelope_rejections": 2,
                  "separator_run_cases": 2}, sort_keys=True))

{"additional_gap_cases": 3, "envelope_rejections": 2, "recovery": {"accepted_ids": ["A", "C"], "gaps": [2], "state": "partial_hold"}, "separator_run_cases": 2}

De echte lokale uitvoer bewaart A en C en meldt lokale kandidaatpositie 2. Dit is geen betrouwbaar bronrecordnummer: bytes kunnen ontbreken, extra RS kan kandidaten splitsen en separatorreeksen tellen niet mee. Aanvullende asserts houden een object zonder laatste LF, een boolean en een numerieke id tegen. Twee envelopfixtures weigeren ontbrekende initiële RS en een te grote buffer. Twee separatorfixtures tonen dat herhaalde en afsluitende RS geen gaten uitvinden. Er is geen netwerkonderbreking gesimuleerd; alleen vooraf samengestelde bytes zijn verwerkt.

Kies apart wat gedeeltelijk bruikbaar is

Een inspectievenster kan intacte records met een opvallende gedeeltelijk-melding tonen. Een consumer die een volledige export nodig heeft, moet het geheel vasthouden en de overeengekomen herstelroute volgen. Dezelfde parse-uitkomst kan dus tot verschillende productacties leiden. Verwijder de gaten niet om een succesvolle teller te krijgen en noem geaccepteerde objecten geen volledige bronkopie.

Dit is geen streamingimplementatie: chunkgrenzen, backpressure en tussentijdse opslag zijn niet getest. Dubbele JSON-namen, dubbele id’s, toepassingsschema’s en niet-eindige getallen vragen afzonderlijke controles. Het voorbeeld voert geen import, retry of write uit en bewijst geen recordvolledigheid. Brononderzoek en synthetische lokale uitvoering zijn gedaan; toegang, rechten en onafhankelijke feiten- en vertaalreview zijn geen onderdeel van dit resultaat.

Bronnen & onderbouwing

  1. Oorspronkelijke brontitel: RFC 7464 — JavaScript Object Notation (JSON) Text Sequences

    Geraadpleegd: 2026-10-18T22:58:31.189040+00:00

Een keuzehulp voor jouw situatie

Je antwoorden blijven in deze pagina tot je ze zelf indient. Niet-opgeslagen antwoorden verdwijnen bij herladen.

Opslaan is nog niet ingesteld. Er worden geen antwoorden of contactgegevens verzonden of bewaard.

Welke integratiestap helpt je verder?

30 korte vragen over API’s en gegevens koppelen. Een antwoord kiezen gaat automatisch verder. Je kunt teruggaan, wijzigen en overslaan. Dit is een praktische leesroute, geen wetenschappelijke test.

JavaScript is nodig voor deze keuzehulp.

Contact & correcties

Stuur een vraag of meld een correctie via dit formulier.

Alleen na Verzenden worden je naam, e-mailadres, onderwerp en bericht naar de contactdienst gestuurd om je bericht te behandelen. Dit is geen nieuwsbriefinschrijving. Niet-verzonden tekst verdwijnt bij herladen. Privacyinformatie

Voorbeeld: verzenden is niet ingesteld. Dit formulier verzendt of bewaart niets.

Je bericht — alle velden zijn verplicht