Respuesta 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...
Mostrar respuesta completa ▼
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
Resultado
Votos ganadores
3 / 3
Puntuacion media
Puntuacion total
Comentario general
La respuesta A es una implementación bien elaborada que maneja correctamente las seis operaciones de JSON Patch con una cuidadosa atención a los casos límite. Las fortalezas clave incluyen: una función _deep_equal adecuada que distingue correctamente los booleanos de los enteros (crítico para la operación de prueba), la verificación de descendientes a nivel de token para la operación de movimiento usando _is_prefix, la validación correcta del escape ~ en _unescape_token, la validación exacta de campos usando el diccionario _REQUIRED_FIELDS y la atomicidad adecuada mediante copias profundas antes de cualquier mutación. El código está bien organizado con funciones auxiliares claras y es prácticamente fiable.
Ver detalle de evaluacion ▼
Correccion
Peso 35%La respuesta A implementa correctamente las seis operaciones con validación cuidadosa. La función _deep_equal maneja adecuadamente la distinción de tipos bool/int, lo cual es crítico para la operación de prueba. La operación de movimiento verifica correctamente las rutas descendientes mediante la comparación a nivel de token. La función _unescape_token valida correctamente que ~ solo va seguido de 0 o 1. La validación del índice de matriz rechaza correctamente los ceros iniciales. La atomicidad se conserva copiando en profundidad el documento antes de cualquier mutación. Un problema menor: en la operación de movimiento, mover una ruta a sí misma (from_tokens == path_tokens) no se maneja explícitamente como una operación nula, pero el código aún funcionaría (eliminar y volver a agregar). En general, una corrección muy sólida.
Integridad
Peso 20%La respuesta A implementa las seis operaciones requeridas (add, remove, replace, move, copy, test), maneja el reemplazo del documento raíz, valida la sintaxis de JSON Pointer, incluidas las secuencias ~ inválidas, valida los índices de matriz, incluidos los ceros iniciales, valida los campos de operación exactamente (sin extras, sin faltantes), maneja el token '-' para la adición a la matriz y copia valores en profundidad apropiadamente. El diccionario _REQUIRED_FIELDS garantiza una validación exacta de los campos. Se abordan todos los casos límite mencionados en la especificación.
Calidad del codigo
Peso 20%La respuesta A está bien estructurada con funciones auxiliares claras, cada una con una única responsabilidad. El diccionario _REQUIRED_FIELDS es un enfoque elegante para la validación de campos. El código es legible y mantenible. La función _deep_equal está cuidadosamente implementada. La función _is_prefix para la validación de movimientos es limpia. Problema menor: el código duplica algo de lógica entre _do_add, _do_remove, _do_replace en lugar de usar un ayudante de recorrido compartido, pero esto es aceptable por claridad.
Valor practico
Peso 15%La respuesta A es prácticamente muy útil. Maneja correctamente todos los casos límite que importan en el uso real de JSON Patch, incluida la distinción bool/int en las operaciones de prueba, la verificación adecuada de descendientes a nivel de token para el movimiento y la validación correcta del escape ~. La garantía de atomicidad se implementa correctamente. El código funcionaría correctamente en escenarios de producción.
Seguimiento de instrucciones
Peso 10%La respuesta A sigue todas las instrucciones: utiliza Python 3.11, implementa apply_json_patch(document, patch), define JsonPatchError, utiliza solo la biblioteca estándar (módulo copy), no muta el documento original, genera JsonPatchError para operaciones inválidas, maneja las seis operaciones, valida la sintaxis de JSON Pointer, maneja todos los casos límite especificados. La firma de la función y el nombre de la clase coinciden exactamente.
Puntuacion total
Comentario general
La Respuesta A proporciona una implementación sólida y en gran medida correcta de JSON Patch. Su análisis de JSON Pointer, la validación de índices de matriz y la lógica de igualdad profunda de la operación `test` son particularmente sólidos y se adhieren bien a la especificación. El código está bien estructurado y es legible, con una clara separación de responsabilidades en funciones auxiliares. El principal inconveniente es un error semántico en la operación `move`, donde copia profundamente el valor en lugar de mover la referencia, lo que se desvía del comportamiento estándar de JSON Patch.
Ver detalle de evaluacion ▼
Correccion
Peso 35%La Respuesta A proporciona una implementación muy correcta. Su análisis de JSON Pointer para secuencias de escape es robusto, y la función `_deep_equal` para la operación `test` implementa correctamente la igualdad consciente del tipo especificada. El único problema de corrección notable es que la operación `move` copia profundamente el valor en lugar de mover la referencia, lo que es una desviación semántica del JSON Patch estándar.
Integridad
Peso 20%La Respuesta A implementa completamente las seis operaciones requeridas de JSON Patch (add, remove, replace, move, copy, test), la excepción personalizada `JsonPatchError` y todas las reglas de análisis de JSON Pointer especificadas. Todas las características solicitadas en el prompt están presentes.
Calidad del codigo
Peso 20%El código de la Respuesta A está bien estructurado con funciones auxiliares claras y enfocadas. Los nombres de las variables son descriptivos y la lógica es generalmente explícita en lugar de depender de un manejo amplio de excepciones. La función `_deep_equal` es un buen ejemplo de lógica clara y robusta. Esto contribuye a una alta legibilidad y mantenibilidad.
Valor practico
Peso 15%La Respuesta A proporciona una implementación de JSON Patch muy funcional y confiable. Su análisis robusto y la operación `test` correcta la hacen adecuada para uso práctico, a pesar de la desviación semántica menor en la operación `move`. La garantía de atomicidad también está bien implementada.
Seguimiento de instrucciones
Peso 10%La Respuesta A sigue casi todas las instrucciones con precisión, incluida la excepción personalizada, la no mutación, todas las operaciones, las reglas de JSON Pointer (desescapado, ceros iniciales, reglas de índice de matriz, '-' para agregar), la igualdad profunda para `test` y la validación exacta de campos para las operaciones. La única desviación menor es el comportamiento de copia profunda en la operación `move`, que no son las semánticas estándar de JSON Patch.
Puntuacion total
Comentario general
La respuesta A es una implementación sólida y ejecutable con funciones auxiliares claras, copias profundas adecuadas del documento original, validación exacta de campos de operación, buena validación de escape de punteros JSON, manejo robusto de índices de matrices y soporte para todas las operaciones requeridas. Sus principales debilidades son los casos extremos: rechaza la adición de un miembro de objeto llamado '-' aunque '-' solo debe ser especial para matrices, rechaza los casos de eliminación y movimiento de la raíz, y un valor de operación no hasheable y no cadena podría escapar como un TypeError en lugar de JsonPatchError. En general, es sustancialmente correcto y mantenible.
Ver detalle de evaluacion ▼
Correccion
Peso 35%Mayormente correcto en todas las operaciones, con un análisis de punteros sólido, validación de índices de matrices, atomicidad con respecto al documento original y comportamiento de copia profunda. Pierde puntos por rechazar la adición de objetos a la clave '-', rechazar casos de movimiento/eliminación de la raíz y potencialmente lanzar TypeError en lugar de JsonPatchError para un valor de operación no hasheable.
Integridad
Peso 20%Implementa las seis operaciones requeridas, conjuntos de campos exactos, decodificación de punteros JSON, reglas de límites y ceros iniciales de matrices, adición/reemplazo de raíz, rechazo de descendientes de movimiento y copias profundas. La completitud se reduce por algunos casos extremos en torno a '-' como clave de objeto y el comportamiento de movimiento/eliminación de la raíz.
Calidad del codigo
Peso 20%Código bien estructurado con ayudantes enfocados para análisis, navegación, mutación, igualdad y validación. La implementación es fácil de seguir y evita depender de excepciones accidentales de Python en la mayoría de los lugares, aunque hay un pequeño parámetro no utilizado y algunas validaciones de casos extremos son imperfectas.
Valor practico
Peso 15%Sería confiable en la mayoría de los casos de uso prácticos de JSON Patch, protege bien la entrada original y proporciona fallos deterministas de JsonPatchError para casi todos los parches mal formados. Los problemas restantes son casos extremos relativamente infrecuentes.
Seguimiento de instrucciones
Peso 10%Sigue de cerca la indicación al proporcionar código compatible con Python 3.11, la función y la excepción solicitadas, implementación solo con bibliotecas estándar, todas las operaciones compatibles, sin CLI y una fuerte no mutación del documento original. Persisten desviaciones menores en la semántica de las rutas de casos extremos y el envoltorio de algunos errores.