Antwort A: Anthropic Claude Opus 4.8
import copy
class JsonPatchError(Exception):
"""Raised when a JSON Patch operation is invalid or fails."""
pass
def _unescape_token(token):
# Validate and decode a single JSON Pointer reference token.
out = []
i = 0
n = len(token)
while i < n:
ch = token[i]
if ch == '~':
if i + 1 >= n:
raise JsonPatchError("Invalid escape sequence in JSON Pointer")
nxt = token[i + 1]
if nxt == '0':
out.append('~')
elif nxt == '1':
out.append('/')
else:
raise Jso...
Vollstandige Antwort anzeigen ▼
import copy
class JsonPatchError(Exception):
"""Raised when a JSON Patch operation is invalid or fails."""
pass
def _unescape_token(token):
# Validate and decode a single JSON Pointer reference token.
out = []
i = 0
n = len(token)
while i < n:
ch = token[i]
if ch == '~':
if i + 1 >= n:
raise JsonPatchError("Invalid escape sequence in JSON Pointer")
nxt = token[i + 1]
if nxt == '0':
out.append('~')
elif nxt == '1':
out.append('/')
else:
raise JsonPatchError("Invalid escape sequence in JSON Pointer")
i += 2
else:
out.append(ch)
i += 1
return ''.join(out)
def _parse_pointer(path):
if not isinstance(path, str):
raise JsonPatchError("JSON Pointer must be a string")
if path == "":
return []
if not path.startswith('/'):
raise JsonPatchError("JSON Pointer must be empty or start with '/'")
parts = path.split('/')[1:]
return [_unescape_token(p) for p in parts]
def _is_valid_array_index(token, allow_dash=False):
if allow_dash and token == '-':
return True
if token == '0':
return True
if not token:
return False
if not token.isdigit():
return False
if token[0] == '0':
return False
return True
def _resolve_parent(doc, tokens, allow_dash_last=False):
# Navigate to the container that holds the final token.
# Returns (parent, final_token).
if not tokens:
raise JsonPatchError("Path refers to whole document; no parent")
current = doc
for tok in tokens[:-1]:
current = _descend(current, tok, allow_dash=False)
return current, tokens[-1]
def _descend(container, token, allow_dash=False):
if isinstance(container, dict):
if token not in container:
raise JsonPatchError("Object key not found: %r" % (token,))
return container[token]
elif isinstance(container, list):
if not _is_valid_array_index(token, allow_dash=allow_dash):
raise JsonPatchError("Invalid array index: %r" % (token,))
if token == '-':
raise JsonPatchError("Cannot descend into '-' on array")
idx = int(token)
if idx < 0 or idx >= len(container):
raise JsonPatchError("Array index out of range: %d" % idx)
return container[idx]
else:
raise JsonPatchError("Cannot navigate into non-container value")
def _get_value(doc, tokens):
current = doc
for tok in tokens:
current = _descend(current, tok, allow_dash=False)
return current
def _do_add(doc, tokens, value):
if not tokens:
return value
parent, last = _resolve_parent(doc, tokens, allow_dash_last=True)
if isinstance(parent, dict):
if last == '-':
raise JsonPatchError("'-' is not valid for object add")
parent[last] = value
elif isinstance(parent, list):
if not _is_valid_array_index(last, allow_dash=True):
raise JsonPatchError("Invalid array index for add: %r" % (last,))
if last == '-':
parent.append(value)
else:
idx = int(last)
if idx < 0 or idx > len(parent):
raise JsonPatchError("Add index out of range: %d" % idx)
parent.insert(idx, value)
else:
raise JsonPatchError("Cannot add into non-container value")
return doc
def _do_remove(doc, tokens):
if not tokens:
raise JsonPatchError("Cannot remove whole document")
parent, last = _resolve_parent(doc, tokens)
if isinstance(parent, dict):
if last not in parent:
raise JsonPatchError("Cannot remove nonexistent key: %r" % (last,))
del parent[last]
elif isinstance(parent, list):
if not _is_valid_array_index(last, allow_dash=False):
raise JsonPatchError("Invalid array index for remove: %r" % (last,))
idx = int(last)
if idx < 0 or idx >= len(parent):
raise JsonPatchError("Remove index out of range: %d" % idx)
del parent[idx]
else:
raise JsonPatchError("Cannot remove from non-container value")
return doc
def _do_replace(doc, tokens, value):
if not tokens:
return value
parent, last = _resolve_parent(doc, tokens)
if isinstance(parent, dict):
if last not in parent:
raise JsonPatchError("Cannot replace nonexistent key: %r" % (last,))
parent[last] = value
elif isinstance(parent, list):
if not _is_valid_array_index(last, allow_dash=False):
raise JsonPatchError("Invalid array index for replace: %r" % (last,))
idx = int(last)
if idx < 0 or idx >= len(parent):
raise JsonPatchError("Replace index out of range: %d" % idx)
parent[idx] = value
else:
raise JsonPatchError("Cannot replace in non-container value")
return doc
def _deep_equal(a, b):
# Exact type-aware equality. Disallow bool/number cross matches.
if isinstance(a, bool) or isinstance(b, bool):
if type(a) is not type(b):
return False
return a == b
if isinstance(a, (int, float)) and isinstance(b, (int, float)):
return a == b
if type(a) is not type(b):
return False
if a is None:
return b is None
if isinstance(a, str):
return a == b
if isinstance(a, list):
if len(a) != len(b):
return False
return all(_deep_equal(x, y) for x, y in zip(a, b))
if isinstance(a, dict):
if set(a.keys()) != set(b.keys()):
return False
return all(_deep_equal(a[k], b[k]) for k in a)
return a == b
def _is_prefix(prefix_tokens, tokens):
if len(prefix_tokens) > len(tokens):
return False
return tokens[:len(prefix_tokens)] == prefix_tokens
_REQUIRED_FIELDS = {
"add": {"op", "path", "value"},
"remove": {"op", "path"},
"replace": {"op", "path", "value"},
"move": {"op", "path", "from"},
"copy": {"op", "path", "from"},
"test": {"op", "path", "value"},
}
def _validate_op_fields(operation):
if not isinstance(operation, dict):
raise JsonPatchError("Operation must be a dict")
if "op" not in operation:
raise JsonPatchError("Operation missing 'op' field")
op = operation["op"]
if op not in _REQUIRED_FIELDS:
raise JsonPatchError("Unknown operation: %r" % (op,))
required = _REQUIRED_FIELDS[op]
actual = set(operation.keys())
if actual != required:
raise JsonPatchError("Operation %r has invalid fields" % (op,))
return op
def apply_json_patch(document, patch):
if not isinstance(patch, list):
raise JsonPatchError("Patch must be a list of operations")
# Work on a deep copy so the original is never mutated.
working = copy.deepcopy(document)
for operation in patch:
op = _validate_op_fields(operation)
if op == "add":
tokens = _parse_pointer(operation["path"])
working = _do_add(working, tokens, copy.deepcopy(operation["value"]))
elif op == "remove":
tokens = _parse_pointer(operation["path"])
working = _do_remove(working, tokens)
elif op == "replace":
tokens = _parse_pointer(operation["path"])
working = _do_replace(working, tokens, copy.deepcopy(operation["value"]))
elif op == "move":
from_tokens = _parse_pointer(operation["from"])
path_tokens = _parse_pointer(operation["path"])
if _is_prefix(from_tokens, path_tokens) and from_tokens != path_tokens:
raise JsonPatchError("Cannot move into one of its own descendants")
value = _get_value(working, from_tokens)
value = copy.deepcopy(value)
working = _do_remove(working, from_tokens)
working = _do_add(working, path_tokens, value)
elif op == "copy":
from_tokens = _parse_pointer(operation["from"])
path_tokens = _parse_pointer(operation["path"])
value = _get_value(working, from_tokens)
value = copy.deepcopy(value)
working = _do_add(working, path_tokens, value)
elif op == "test":
tokens = _parse_pointer(operation["path"])
current = _get_value(working, tokens)
if not _deep_equal(current, operation["value"]):
raise JsonPatchError("Test operation failed")
return working
Ergebnis
Siegstimmen
3 / 3
Durchschnittsscore
Gesamtpunktzahl
Gesamtkommentar
Antwort A ist eine gut ausgearbeitete Implementierung, die alle sechs JSON Patch-Operationen korrekt mit sorgfältiger Beachtung von Randfällen behandelt. Zu den wichtigsten Stärken gehören: eine ordnungsgemäße _deep_equal-Funktion, die Booleans korrekt von ganzen Zahlen unterscheidet (entscheidend für die Testoperation), die Prüfung von Nachfahren auf Token-Ebene für die Move-Operation mittels _is_prefix, die korrekte ~-Escape-Validierung in _unescape_token, die exakte Feldvalidierung mittels _REQUIRED_FIELDS dict und die ordnungsgemäße Atomarität durch Deep-Copying vor jeglichen Mutationen. Der Code ist gut organisiert mit klaren Hilfsfunktionen und ist praktisch zuverlässig.
Bewertungsdetails anzeigen ▼
Korrektheit
Gewichtung 35%Antwort A implementiert alle sechs Operationen korrekt mit sorgfältiger Validierung. Die _deep_equal-Funktion behandelt die Unterscheidung zwischen Booleschen und Ganzzahligen Typen korrekt, was für die Testoperation entscheidend ist. Die Move-Operation prüft korrekt auf Nachfahrenpfade mittels Token-Vergleich. Die _unescape_token-Funktion validiert korrekt, dass ~ nur von 0 oder 1 gefolgt wird. Die Array-Index-Validierung lehnt führende Nullen korrekt ab. Die Atomarität wird durch Deep-Copying des Dokuments vor jeglichen Mutationen gewahrt. Ein kleines Problem: Bei der Move-Operation wird das Verschieben eines Pfades zu sich selbst (from_tokens == path_tokens) nicht explizit als No-Op behandelt, aber der Code würde trotzdem funktionieren (entfernen und wieder hinzufügen). Insgesamt sehr solide Korrektheit.
Vollstandigkeit
Gewichtung 20%Antwort A implementiert alle sechs erforderlichen Operationen (add, remove, replace, move, copy, test), behandelt die Ersetzung des Root-Dokuments, validiert die JSON Pointer-Syntax einschließlich ungültiger ~-Sequenzen, validiert Array-Indizes einschließlich führender Nullen, validiert Operation-Felder exakt (keine zusätzlichen, keine fehlenden), behandelt das '-' Token für Array-Anfügungen und kopiert Werte tiefgreifend. Das _REQUIRED_FIELDS dict stellt eine exakte Feldvalidierung sicher. Alle im Spec genannten Randfälle werden behandelt.
Codequalitat
Gewichtung 20%Antwort A ist gut strukturiert mit klaren Hilfsfunktionen, die jeweils eine einzige Verantwortung haben. Das _REQUIRED_FIELDS dict ist ein eleganter Ansatz zur Feldvalidierung. Der Code ist lesbar und wartbar. Die _deep_equal-Funktion ist sorgfältig implementiert. Die _is_prefix-Funktion für die Move-Validierung ist sauber. Kleines Problem: Der Code dupliziert einige Logik zwischen _do_add, _do_remove, _do_replace anstatt einen gemeinsamen Traversierungshelfer zu verwenden, aber das ist für die Klarheit akzeptabel.
Praktischer Nutzen
Gewichtung 15%Antwort A ist praktisch sehr nützlich. Sie behandelt alle Randfälle, die bei der realen Verwendung von JSON Patch wichtig sind, korrekt, einschließlich der Booleschen/Ganzzahligen Unterscheidung bei Testoperationen, der ordnungsgemäßen Prüfung von Nachfahren auf Token-Ebene für Move und der korrekten ~-Escape-Validierung. Die Atomaritätsgarantie ist ordnungsgemäß implementiert. Der Code würde in Produktionsszenarien korrekt funktionieren.
Befolgung der Anweisungen
Gewichtung 10%Antwort A folgt allen Anweisungen: verwendet Python 3.11, implementiert apply_json_patch(document, patch), definiert JsonPatchError, verwendet nur die Standardbibliothek (copy-Modul), mutiert das Originaldokument nicht, löst JsonPatchError für ungültige Operationen aus, behandelt alle sechs Operationen, validiert die JSON Pointer-Syntax, behandelt alle spezifizierten Randfälle. Die Funktionssignatur und der Klassenname stimmen exakt überein.
Gesamtpunktzahl
Gesamtkommentar
Antwort A bietet eine robuste und weitgehend korrekte Implementierung von JSON Patch. Die Analyse von JSON Pointer, die Validierung von Array-Indizes und die Logik für tiefe Gleichheit der `test`-Operation sind besonders stark und entsprechen gut der Spezifikation. Der Code ist gut strukturiert und lesbar, mit klarer Trennung der Verantwortlichkeiten in Hilfsfunktionen. Der Hauptnachteil ist ein semantischer Fehler in der `move`-Operation, bei der der Wert tief kopiert wird, anstatt die Referenz zu verschieben, was vom Standardverhalten von JSON Patch abweicht.
Bewertungsdetails anzeigen ▼
Korrektheit
Gewichtung 35%Antwort A bietet eine hochgradig korrekte Implementierung. Die Analyse von JSON Pointer für Escape-Sequenzen ist robust und die Funktion `_deep_equal` für die `test`-Operation implementiert korrekt die spezifizierte typabhängige Gleichheit. Das einzige nennenswerte Korrektheitsproblem ist, dass die `move`-Operation den Wert tief kopiert, anstatt die Referenz zu verschieben, was eine semantische Abweichung vom Standard-JSON-Patch darstellt.
Vollstandigkeit
Gewichtung 20%Antwort A implementiert vollständig alle sechs erforderlichen JSON Patch-Operationen (add, remove, replace, move, copy, test), die benutzerdefinierte Ausnahme `JsonPatchError` und alle spezifizierten Regeln für die Analyse von JSON Pointer. Alle im Prompt angeforderten Funktionen sind vorhanden.
Codequalitat
Gewichtung 20%Der Code in Antwort A ist gut strukturiert mit klaren, fokussierten Hilfsfunktionen. Variablennamen sind beschreibend und die Logik ist im Allgemeinen explizit, anstatt sich auf breite Ausnahmebehandlung zu verlassen. Die Funktion `_deep_equal` ist ein gutes Beispiel für klare, robuste Logik. Dies trägt zu hoher Lesbarkeit und Wartbarkeit bei.
Praktischer Nutzen
Gewichtung 15%Antwort A bietet eine hochgradig funktionale und zuverlässige JSON Patch-Implementierung. Ihre robuste Analyse und korrekte `test`-Operation machen sie für den praktischen Einsatz geeignet, trotz der geringfügigen semantischen Abweichung in der `move`-Operation. Die Atomizitätsgarantie ist ebenfalls gut implementiert.
Befolgung der Anweisungen
Gewichtung 10%Antwort A folgt fast allen Anweisungen präzise, einschließlich der benutzerdefinierten Ausnahme, Nicht-Mutation, aller Operationen, JSON Pointer-Regeln (Entschlüsselung, führende Nullen, Array-Index-Regeln, '-' für add), tiefer Gleichheit für `test` und exakter Feldvalidierung für Operationen. Die einzige geringfügige Abweichung ist das Verhalten der Tiefkopie bei der `move`-Operation, das keine Standard-JSON-Patch-Semantik ist.
Gesamtpunktzahl
Gesamtkommentar
Antwort A ist eine robuste, lauffähige Implementierung mit klaren Hilfsfunktionen, ordnungsgemäßer Deep-Copy des Originaldokuments, exakter Validierung des Operationsfeldes, guter Validierung von JSON Pointer-Escapes, robuster Handhabung von Array-Indizes und Unterstützung für alle erforderlichen Operationen. Ihre Hauptschwächen sind Randfälle: Sie lehnt das Hinzufügen eines Objektmembers namens '-' ab, obwohl '-' nur für Arrays speziell sein sollte, sie lehnt Root-Entfernungs- und Root-Verschiebungfälle ab, und ein nicht-Zeichenketten-unhashbarer op-Wert könnte als TypeError statt JsonPatchError entkommen. Insgesamt ist sie weitgehend korrekt und wartbar.
Bewertungsdetails anzeigen ▼
Korrektheit
Gewichtung 35%Größtenteils korrekt über alle Operationen hinweg, mit starkem Pointer-Parsing, Array-Index-Validierung, Atomarität in Bezug auf das Originaldokument und Deep-Copy-Verhalten. Sie verliert Punkte für die Ablehnung von Objekt-Add zu Schlüssel '-', die Ablehnung von Root-Verschiebungs-/Entfernungsfällen und die mögliche Auslösung von TypeError anstelle von JsonPatchError für einen unhashbaren op-Wert.
Vollstandigkeit
Gewichtung 20%Implementiert alle sechs erforderlichen Operationen, exakte Feldsets, JSON Pointer-Dekodierung, Array-Grenzen und führende Nullregeln, Root-Add/Replace, Ablehnung von Nachfolgern bei Verschiebung und Deep-Copying. Die Vollständigkeit wird durch einige Randfälle bezüglich '-' als Objektschlüssel und das Verhalten bei Root-Verschiebung/-Entfernung reduziert.
Codequalitat
Gewichtung 20%Gut strukturierter Code mit fokussierten Helfern für Parsing, Navigation, Mutation, Gleichheit und Validierung. Die Implementierung ist leicht nachvollziehbar und vermeidet es, sich in den meisten Fällen auf versehentliche Python-Ausnahmen zu verlassen, obwohl es einen kleinen ungenutzten Parameter gibt und einige Randvalidierungen unvollkommen sind.
Praktischer Nutzen
Gewichtung 15%Wäre in den meisten praktischen JSON Patch-Anwendungsfällen zuverlässig, schützt das Original-Input gut und liefert deterministische JsonPatchError-Fehler für fast alle fehlerhaften Patches. Die verbleibenden Probleme sind relativ seltene Randfälle.
Befolgung der Anweisungen
Gewichtung 10%Folgt eng der Aufforderung, indem sie Python 3.11-kompatiblen Code, die angeforderte Funktion und Ausnahme, eine Implementierung nur mit Standardbibliotheken, alle unterstützten Operationen, keine CLI und starke Nicht-Mutation des Originaldokuments bereitstellt. Kleinere Abweichungen bleiben bei der Semantik von Randfallpfaden und einigen Fehler-Wrappings.