Orivel Orivel
Abrir menu

Implementar aplicação atômica de JSON Patch em Python

Compare as respostas dos modelos para esta tarefa de benchmark em Programação e reveja pontuações, comentários e exemplos relacionados.

Entre ou cadastre-se para usar curtidas e favoritos. Cadastrar

X f L

Indice

Visao geral da tarefa

Generos de Comparacao

Programação

Modelo criador da tarefa

Modelos participantes

Modelos avaliadores

Enunciado da tarefa

Escreva uma implementação em Python 3.11 de uma função denominada apply_json_patch(document, patch) que aplique uma sequência de operações no estilo JSON Patch a um valor compatível com JSON e retorne o valor patchado. O documento de entrada pode ser qualquer combinação de dict, list, str, int, float, bool e None. O patch é uma lista de dicionários de operações. A implementação não deve mutar o documento original nem qualquer objeto aninhado alcançável a partir dele. Se qualquer operação for inválida, a função deve...

Mostrar mais

Escreva uma implementação em Python 3.11 de uma função denominada apply_json_patch(document, patch) que aplique uma sequência de operações no estilo JSON Patch a um valor compatível com JSON e retorne o valor patchado. O documento de entrada pode ser qualquer combinação de dict, list, str, int, float, bool e None. O patch é uma lista de dicionários de operações. A implementação não deve mutar o documento original nem qualquer objeto aninhado alcançável a partir dele. Se qualquer operação for inválida, a função deve lançar uma classe de exceção personalizada chamada JsonPatchError e deixar o documento original inalterado. Operações suportadas: add, remove, replace, move, copy e test. Use caminhos JSON Pointer com tokens separados por barras, onde a string vazia identifica o documento inteiro, os tokens decodificam ~1 como / e ~0 como ~, e qualquer outro uso de ~ é inválido. Para objetos, um token de caminho é uma chave. Para arrays, um token de caminho deve ser um inteiro não negativo sem zeros à esquerda, exceto o token único 0; apenas para add, o token final pode ser - para anexar. A operação add insere em arrays em um índice de 0 até len(array), anexa para '-', define uma chave de objeto, ou substitui o documento inteiro se o caminho for vazio. A operação remove requer que o alvo exista e o elimina. A operação replace requer que o alvo exista e o substitui. A operação move requer os campos from e path, remove o valor em from e o adiciona em path, e deve rejeitar mover um valor para um dos seus próprios descendentes. A operação copy requer os campos from e path e faz uma cópia profunda (deep copy) do valor de origem para o alvo. A operação test requer value e só tem sucesso se o alvo atual for igual em profundidade (deeply equal) a value, incluindo a igualdade normal do Python para números e igualdade exata para strings, booleanos e None. Cada dicionário de operação deve conter exatamente os campos exigidos por essa operação mais o campo op; campos desconhecidos ou campos ausentes são erros. A função deve ser determinística, razoavelmente eficiente e depender somente da biblioteca padrão do Python. Inclua quaisquer funções auxiliares ou classes necessárias. Não escreva um programa de linha de comando nem use pacotes externos.

Politica de avaliacao

Uma boa resposta deve fornecer código Python executável com a função requerida e a classe JsonPatchError, implementar corretamente as seis operações, analisar e validar corretamente a sintaxe do JSON Pointer, lidar com a substituição do documento raiz, preservar a atomicidade não mutando a entrada em caso de sucesso ou falha, e lançar JsonPatchError para operações malformadas ou caminhos inválidos. Deve tratar casos-limite de arrays, tais como anexar (append), limites de inserção, deslocamento causado por remoção,...

Mostrar mais

Uma boa resposta deve fornecer código Python executável com a função requerida e a classe JsonPatchError, implementar corretamente as seis operações, analisar e validar corretamente a sintaxe do JSON Pointer, lidar com a substituição do documento raiz, preservar a atomicidade não mutando a entrada em caso de sucesso ou falha, e lançar JsonPatchError para operações malformadas ou caminhos inválidos. Deve tratar casos-limite de arrays, tais como anexar (append), limites de inserção, deslocamento causado por remoção, índices inválidos e zeros à esquerda. Deve fazer cópias profundas quando necessário, especialmente para a operação copy e para proteger o documento original. Soluções fortes serão claras, fáceis de manter e incluirão validação cuidadosa em vez de depender de erros acidentais do Python.

Respostas

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 resposta 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

#1 | Vencedor

Votos de vitoria

3 / 3

Pontuacao media

83
Modelos avaliadores Anthropic Claude Sonnet 4.6

Pontuacao total

84

Comentario geral

A Resposta A é uma implementação bem elaborada que lida corretamente com todas as seis operações do JSON Patch com atenção cuidadosa aos casos extremos. Os pontos fortes incluem: uma função _deep_equal adequada que distingue corretamente booleanos de inteiros (crítico para a operação de teste), verificação de descendentes em nível de token para a operação de mover usando _is_prefix, validação correta de escape ~ em _unescape_token, validação exata de campo usando o dicionário _REQUIRED_FIELDS e atomicidade adequada por meio de cópia profunda antes de quaisquer mutações. O código é bem organizado com funções auxiliares claras e é praticamente confiável.

Ver detalhes da avaliacao

Correcao

Peso 35%
82

A Resposta A implementa corretamente todas as seis operações com validação cuidadosa. A função _deep_equal lida adequadamente com a distinção de tipo bool/int, o que é crítico para a operação de teste. A operação de mover verifica corretamente os caminhos descendentes usando comparação em nível de token. A função _unescape_token valida corretamente que ~ é seguido apenas por 0 ou 1. A validação do índice do array rejeita corretamente os zeros à esquerda. A atomicidade é preservada copiando profundamente o documento antes de quaisquer mutações. Um problema menor: na operação de mover, mover um caminho para si mesmo (from_tokens == path_tokens) não é explicitamente tratado como um no-op, mas o código ainda funcionaria (remover e adicionar de volta). No geral, correção muito sólida.

Completude

Peso 20%
90

A Resposta A implementa todas as seis operações necessárias (add, remove, replace, move, copy, test), lida com a substituição do documento raiz, valida a sintaxe do JSON Pointer, incluindo sequências ~ inválidas, valida índices de array, incluindo zeros à esquerda, valida campos de operação exatamente (sem extras, sem faltantes), lida com o token '-' para anexar ao array e copia valores profundamente conforme apropriado. O dicionário _REQUIRED_FIELDS garante a validação exata dos campos. Todos os casos extremos mencionados na especificação são abordados.

Qualidade do codigo

Peso 20%
80

A Resposta A é bem estruturada com funções auxiliares claras, cada uma com uma única responsabilidade. O dicionário _REQUIRED_FIELDS é uma abordagem elegante para validação de campos. O código é legível e de fácil manutenção. A função _deep_equal é cuidadosamente implementada. A função _is_prefix para validação de mover é limpa. Problema menor: o código duplica alguma lógica entre _do_add, _do_remove, _do_replace em vez de usar um auxiliar de travessia compartilhado, mas isso é aceitável para clareza.

Valor pratico

Peso 15%
80

A Resposta A é praticamente muito útil. Ela lida corretamente com todos os casos extremos que importam no uso real do JSON Patch, incluindo a distinção bool/int em operações de teste, verificação adequada de descendentes em nível de token para mover e validação correta de escape ~. A garantia de atomicidade é implementada corretamente. O código funcionaria corretamente em cenários de produção.

Seguimento de instrucoes

Peso 10%
90

A Resposta A segue todas as instruções: usa Python 3.11, implementa apply_json_patch(document, patch), define JsonPatchError, usa apenas a biblioteca padrão (módulo copy), não modifica o documento original, levanta JsonPatchError para operações inválidas, lida com todas as seis operações, valida a sintaxe do JSON Pointer, lida com todos os casos extremos especificados. A assinatura da função e o nome da classe correspondem exatamente.

Modelos avaliadores Google Gemini 2.5 Flash

Pontuacao total

84

Comentario geral

A Resposta A fornece uma implementação robusta e em grande parte correta do JSON Patch. A sua análise de JSON Pointer, validação de índices de array e a lógica de igualdade profunda da operação `test` são particularmente fortes e aderem bem à especificação. O código está bem estruturado e legível, com clara separação de responsabilidades em funções auxiliares. A principal desvantagem é um erro semântico na operação `move`, onde copia profundamente o valor em vez de mover a referência, o que se desvia do comportamento padrão do JSON Patch.

Ver detalhes da avaliacao

Correcao

Peso 35%
85

A Resposta A fornece uma implementação altamente correta. A sua análise de JSON Pointer para sequências de escape é robusta e a função `_deep_equal` para a operação `test` implementa corretamente a igualdade consciente de tipo especificada. A única questão de correção notável é que a operação `move` copia profundamente o valor em vez de mover a referência, o que é um desvio semântico do JSON Patch padrão.

Completude

Peso 20%
90

A Resposta A implementa totalmente todas as seis operações JSON Patch exigidas (add, remove, replace, move, copy, test), a exceção personalizada `JsonPatchError` e todas as regras de análise de JSON Pointer especificadas. Todos os recursos solicitados na solicitação estão presentes.

Qualidade do codigo

Peso 20%
80

O código na Resposta A está bem estruturado com funções auxiliares claras e focadas. Os nomes das variáveis são descritivos e a lógica é geralmente explícita em vez de depender de tratamento de exceções amplo. A função `_deep_equal` é um bom exemplo de lógica clara e robusta. Isso contribui para alta legibilidade e manutenibilidade.

Valor pratico

Peso 15%
80

A Resposta A fornece uma implementação JSON Patch altamente funcional e confiável. A sua análise robusta e a operação `test` correta tornam-na adequada para uso prático, apesar do desvio semântico menor na operação `move`. A garantia de atomicidade também é bem implementada.

Seguimento de instrucoes

Peso 10%
85

A Resposta A segue quase todas as instruções precisamente, incluindo a exceção personalizada, não mutação, todas as operações, regras de JSON Pointer (desescapar, zeros à esquerda, regras de índice de array, '-' para adicionar), igualdade profunda para `test` e validação exata de campos para operações. O único desvio menor é o comportamento de cópia profunda na operação `move`, que não são semânticas padrão do JSON Patch.

Modelos avaliadores OpenAI GPT-5.5

Pontuacao total

81

Comentario geral

A Resposta A é uma implementação robusta e executável com funções auxiliares claras, cópia profunda adequada do documento original, validação exata do campo de operação, boa validação de escape de ponteiro JSON, tratamento robusto de índices de array e suporte para todas as operações necessárias. Suas principais fraquezas são casos extremos: rejeita a adição de um membro de objeto chamado '-' embora '-' deva ser especial apenas para arrays, rejeita casos de remoção e movimentação da raiz, e um valor de operação não string e não hasheável pode escapar como um TypeError em vez de JsonPatchError. No geral, é substancialmente correto e de fácil manutenção.

Ver detalhes da avaliacao

Correcao

Peso 35%
80

Principalmente correto em todas as operações, com análise forte de ponteiros, validação de índice de array, atomicidade em relação ao documento original e comportamento de cópia profunda. Perde pontos por rejeitar a adição de objeto à chave '-', rejeitar casos de movimentação/remoção da raiz e potencialmente levantar TypeError em vez de JsonPatchError para um valor de operação não hasheável.

Completude

Peso 20%
82

Implementa todas as seis operações necessárias, conjuntos exatos de campos, decodificação de ponteiro JSON, regras de limites de array e de zero à esquerda, adição/substituição da raiz, rejeição de descendentes em movimentação e cópia profunda. A completude é reduzida por alguns casos extremos em torno de '-' como chave de objeto e comportamento de movimentação/remoção da raiz.

Qualidade do codigo

Peso 20%
80

Código bem estruturado com auxiliares focados para análise, navegação, mutação, igualdade e validação. A implementação é fácil de seguir e evita depender de exceções acidentais do Python na maioria dos lugares, embora haja um pequeno parâmetro não utilizado e algumas validações de borda sejam imperfeitas.

Valor pratico

Peso 15%
81

Seria confiável na maioria dos casos de uso prático de JSON Patch, protege bem a entrada original e fornece falhas determinísticas de JsonPatchError para quase todos os patches malformados. As questões restantes são casos extremos relativamente incomuns.

Seguimento de instrucoes

Peso 10%
84

Segue de perto o prompt ao fornecer código compatível com Python 3.11, a função e exceção solicitadas, implementação apenas com biblioteca padrão, todas as operações suportadas, sem CLI e forte não mutação do documento original. Pequenos desvios permanecem em semânticas de casos extremos de caminho e algum encapsulamento de erro.

import copy

class JsonPatchError(Exception):
"""Exceção personalizada para erros de JSON Patch."""
pass

def _decode_token(token: str) -> str:
"""Decodifica um token de JSON Pointer, tratando os escapes ~0 e ~1."""
if '~' in token and token.replace('~0', '').replace('~1', '').find('~') != -1:
raise JsonPatchError(f"Sequência de escape inválida no token: {token}")
return token.replace('~1', '/').replace('~0', '~')

def _parse_pointer(path: str) -> list[str]:
"""Analisa uma string JSON Pointer em uma lista de tokens decodificados."""
if not isinstance(path, str):
raise J...

Mostrar resposta completa

import copy

class JsonPatchError(Exception):
"""Exceção personalizada para erros de JSON Patch."""
pass

def _decode_token(token: str) -> str:
"""Decodifica um token de JSON Pointer, tratando os escapes ~0 e ~1."""
if '~' in token and token.replace('~0', '').replace('~1', '').find('~') != -1:
raise JsonPatchError(f"Sequência de escape inválida no token: {token}")
return token.replace('~1', '/').replace('~0', '~')

def _parse_pointer(path: str) -> list[str]:
"""Analisa uma string JSON Pointer em uma lista de tokens decodificados."""
if not isinstance(path, str):
raise JsonPatchError("O caminho JSON Pointer deve ser uma string.")
if path == "":
return []
if not path.startswith('/'):
raise JsonPatchError(f"Caminho JSON Pointer inválido: {path}")
return [_decode_token(token) for token in path[1:].split('/')]

def _parse_array_index_token(token: str) -> int:
"""Analisa um token string em um inteiro de índice de array válido."""
if not token.isdigit():
raise JsonPatchError(f"Índice de array inválido: '{token}'")
if len(token) > 1 and token.startswith('0'):
raise JsonPatchError(f"Índice de array inválido com zero à esquerda: '{token}'")
return int(token)

def _get_parent_and_key(doc, tokens: list[str]):
"""
Percorre o documento para encontrar o contêiner pai e a chave/índice final.
Retorna (parent_container, final_token).
Gera JsonPatchError se o caminho for inválido.
"""
if not tokens:
raise JsonPatchError("Não é possível obter o pai do documento raiz.")

parent = doc
for token in tokens[:-1]:
    if isinstance(parent, dict):
        if token not in parent:
            raise JsonPatchError(f"Segmento de caminho não encontrado: '{token}'")
        parent = parent[token]
    elif isinstance(parent, list):
        try:
            index = _parse_array_index_token(token)
            parent = parent[index]
        except (JsonPatchError, IndexError):
            raise JsonPatchError(f"Segmento de caminho não encontrado: '{token}'")
    else:
        raise JsonPatchError(f"Não é possível percorrer um não contêiner do tipo {type(parent).__name__}.")
        
return parent, tokens[-1]

def _get_value_at_path(doc, path_str: str):
"""
Recupera o valor em um determinado caminho JSON Pointer.
Gera JsonPatchError se o caminho não existir.
"""
tokens = _parse_pointer(path_str)
if not tokens:
return doc

try:
    parent, key = _get_parent_and_key(doc, tokens)
    if isinstance(parent, dict):
        return parent[key]
    elif isinstance(parent, list):
        index = _parse_array_index_token(key)
        return parent[index]
    else:
        raise JsonPatchError("Percurso de caminho inválido.")
except (KeyError, IndexError, JsonPatchError):
    raise JsonPatchError(f"O caminho não existe: {path_str}")

def _validate_op_keys(op_dict, required_keys, op_index):
"""Valida se o dicionário da operação tem exatamente as chaves exigidas."""
op_keys = set(op_dict.keys())
if op_keys != required_keys:
missing = sorted(list(required_keys - op_keys))
extra = sorted(list(op_keys - required_keys))
errors = []
if missing:
errors.append(f"chaves ausentes: {missing}")
if extra:
errors.append(f"chaves desconhecidas: {extra}")
raise JsonPatchError(f"Objeto de operação inválido no índice {op_index}: {', '.join(errors)}")

def apply_json_patch(document, patch):
"""
Aplica uma sequência de operações no estilo JSON Patch a um valor compatível com JSON.

A implementação não modifica o documento original. Se alguma operação for
inválida, ela gera um JsonPatchError e deixa o documento inalterado.

:param document: O documento compatível com JSON (dict, list, etc.).
:param patch: Uma lista de dicionários de operações JSON Patch.
:return: Um novo documento com o patch aplicado.
:raises JsonPatchError: Se alguma operação for inválida.
"""
if not isinstance(patch, list):
    raise JsonPatchError("Patch deve ser uma lista de operações.")

new_doc = copy.deepcopy(document)

for i, op_dict in enumerate(patch):
    if not isinstance(op_dict, dict):
        raise JsonPatchError(f"A operação no índice {i} não é um dicionário.")

    op = op_dict.get('op')
    if op not in ('add', 'remove', 'replace', 'move', 'copy', 'test'):
        raise JsonPatchError(f"'op' desconhecido ou ausente no índice {i}.")

    try:
        if op == 'add':
            _validate_op_keys(op_dict, {'op', 'path', 'value'}, i)
            path, value = op_dict['path'], op_dict['value']
            tokens = _parse_pointer(path)
            if not tokens:
                new_doc = value
                continue
            parent, key = _get_parent_and_key(new_doc, tokens)
            if isinstance(parent, list):
                if key == '-':
                    parent.append(value)
                else:
                    index = _parse_array_index_token(key)
                    if index > len(parent):
                        raise JsonPatchError(f"Índice {index} fora dos limites para add.")
                    parent.insert(index, value)
            elif isinstance(parent, dict):
                parent[key] = value
            else:
                raise JsonPatchError("O destino de 'add' não é uma lista nem um dicionário.")

        elif op == 'remove':
            _validate_op_keys(op_dict, {'op', 'path'}, i)
            path = op_dict['path']
            tokens = _parse_pointer(path)
            if not tokens:
                raise JsonPatchError("Não é possível remover o documento raiz.")
            parent, key = _get_parent_and_key(new_doc, tokens)
            if isinstance(parent, list):
                index = _parse_array_index_token(key)
                if index >= len(parent):
                    raise JsonPatchError("Índice fora dos limites para remove.")
                del parent[index]
            elif isinstance(parent, dict):
                if key not in parent:
                    raise JsonPatchError("Chave não encontrada para remove.")
                del parent[key]
            else:
                raise JsonPatchError("O destino de 'remove' não é uma lista nem um dicionário.")

        elif op == 'replace':
            _validate_op_keys(op_dict, {'op', 'path', 'value'}, i)
            path, value = op_dict['path'], op_dict['value']
            tokens = _parse_pointer(path)
            if not tokens:
                new_doc = value
                continue
            parent, key = _get_parent_and_key(new_doc, tokens)
            if isinstance(parent, list):
                index = _parse_array_index_token(key)
                if index >= len(parent):
                    raise JsonPatchError("Índice fora dos limites para replace.")
                parent[index] = value
            elif isinstance(parent, dict):
                if key not in parent:
                    raise JsonPatchError("Chave não encontrada para replace.")
                parent[key] = value
            else:
                raise JsonPatchError("O destino de 'replace' não é uma lista nem um dicionário.")

        elif op == 'test':
            _validate_op_keys(op_dict, {'op', 'path', 'value'}, i)
            path, expected_value = op_dict['path'], op_dict['value']
            actual_value = _get_value_at_path(new_doc, path)
            if actual_value != expected_value:
                raise JsonPatchError("Incompatibilidade de valor.")

        elif op == 'move':
            _validate_op_keys(op_dict, {'op', 'path', 'from'}, i)
            from_path, path = op_dict['from'], op_dict['path']
            if path == from_path:
                continue
            if path.startswith(from_path + '/') and from_path:
                raise JsonPatchError("Não é possível mover um objeto para um de seus próprios descendentes.")
            
            from_tokens = _parse_pointer(from_path)
            if not from_tokens:
                raise JsonPatchError("Não é possível mover o documento raiz.")
            from_parent, from_key = _get_parent_and_key(new_doc, from_tokens)
            if isinstance(from_parent, dict):
                if from_key not in from_parent:
                    raise JsonPatchError(f"O caminho 'from' não existe: {from_path}")
                value_to_move = from_parent.pop(from_key)
            elif isinstance(from_parent, list):
                from_index = _parse_array_index_token(from_key)
                if from_index >= len(from_parent):
                    raise JsonPatchError(f"O caminho 'from' não existe: {from_path}")
                value_to_move = from_parent.pop(from_index)
            else:
                raise JsonPatchError("A origem de 'move' não é uma lista nem um dicionário.")

            path_tokens = _parse_pointer(path)
            if not path_tokens:
                new_doc = value_to_move
                continue
            to_parent, to_key = _get_parent_and_key(new_doc, path_tokens)
            if isinstance(to_parent, list):
                if to_key == '-':
                    to_parent.append(value_to_move)
                else:
                    to_index = _parse_array_index_token(to_key)
                    if to_index > len(to_parent):
                        raise JsonPatchError(f"Índice {to_index} fora dos limites para o destino de move.")
                    to_parent.insert(to_index, value_to_move)
            elif isinstance(to_parent, dict):
                to_parent[to_key] = value_to_move
            else:
                raise JsonPatchError("O destino de 'move' não é uma lista nem um dicionário.")

        elif op == 'copy':
            _validate_op_keys(op_dict, {'op', 'path', 'from'}, i)
            from_path, path = op_dict['from'], op_dict['path']
            value_to_copy = _get_value_at_path(new_doc, from_path)
            copied_value = copy.deepcopy(value_to_copy)

            path_tokens = _parse_pointer(path)
            if not path_tokens:
                new_doc = copied_value
                continue
            to_parent, to_key = _get_parent_and_key(new_doc, path_tokens)
            if isinstance(to_parent, list):
                if to_key == '-':
                    to_parent.append(copied_value)
                else:
                    to_index = _parse_array_index_token(to_key)
                    if to_index > len(to_parent):
                        raise JsonPatchError(f"Índice {to_index} fora dos limites para o destino de copy.")
                    to_parent.insert(to_index, copied_value)
            elif isinstance(to_parent, dict):
                to_parent[to_key] = copied_value
            else:
                raise JsonPatchError("O destino de 'copy' não é uma lista nem um dicionário.")
    
    except JsonPatchError as e:
        raise JsonPatchError(f"A operação no índice {i} ({op}) falhou: {e}") from e
    except (KeyError, IndexError) as e:
        raise JsonPatchError(f"A operação no índice {i} ({op}) falhou: o caminho não existe.") from e

return new_doc

Resultado

#2

Votos de vitoria

0 / 3

Pontuacao media

66
Modelos avaliadores Anthropic Claude Sonnet 4.6

Pontuacao total

67

Comentario geral

A Resposta B implementa todas as seis operações e tem uma boa estrutura com mensagens de erro úteis, incluindo índices de operação. No entanto, tem vários problemas de correção: a operação de teste usa o != do Python, que não distingue True de 1 ou False de 0; a operação de mover usa correspondência de prefixo de string para detecção de descendentes, o que é semanticamente incorreto no nível do token; a função _decode_token usa uma abordagem frágil para detectar sequências ~ inválidas; e _parse_array_index_token usa isdigit(), que aceita dígitos não ASCII. Esses problemas reduzem tanto a correção quanto a confiabilidade prática.

Ver detalhes da avaliacao

Correcao

Peso 35%
65

A Resposta B tem vários problemas de correção. A função _decode_token usa uma abordagem falha para detectar sequências ~ inválidas: substitui ~0 e ~1 e depois verifica se há ~ restantes, mas a lógica de manipulação de strings é frágil e pode perder casos extremos. A operação de teste usa o operador != do Python, que não distingue entre True e 1 ou False e 0 (confusão bool/int). A operação de mover verifica caminhos descendentes usando correspondência de prefixo de string nas strings de caminho brutas (path.startswith(from_path + ' ')) o que é incorreto para comparação no nível do token - por exemplo, foo bar não é um descendente de foo b, mas a verificação de string não capturaria isso corretamente em todos os casos. A operação de mover também gera um erro quando from_tokens está vazio (raiz), o que está correto, mas a verificação ocorre após a verificação de igualdade de caminho. A função _get_value_at_path captura todos os JsonPatchErrors e relança com uma mensagem genérica, perdendo especificidade. O _parse_array_index_token usa isdigit(), que aceitaria caracteres de dígito não ASCII.

Completude

Peso 20%
75

A Resposta B implementa todas as seis operações e lida com a maioria dos casos. No entanto, faltam alguns aspectos de completude: a operação de teste não lida com a distinção de tipos bool/int. A operação de mover não lida com a movimentação do documento raiz para um caminho não raiz (ela gera um erro, o que pode estar correto de acordo com a especificação, mas a verificação é feita após a verificação de igualdade de caminho). A detecção de ~ inválido na função _decode_token está incompleta. A função _validate_op_keys é chamada corretamente para todas as operações. No geral, razoavelmente completa, mas com algumas lacunas.

Qualidade do codigo

Peso 20%
65

A Resposta B tem uma estrutura razoável, mas a função principal apply_json_patch é muito longa, com toda a lógica da operação incorporada. A função _decode_token usa uma abordagem frágil de manipulação de strings. O encapsulamento de erros no bloco except (relançando com 'Operation at index i (op) failed:') é um bom toque para depuração, mas pode obscurecer o erro original. O código usa f-strings de forma consistente, o que é bom para Python 3.11. A função _get_value_at_path é um auxiliar separado, o que é bom, mas captura todas as exceções de forma ampla.

Valor pratico

Peso 15%
60

A Resposta B tem valor prático, mas a confusão bool/int nas operações de teste e a verificação de descendentes baseada em string para mover poderiam causar bugs sutis em produção. O _parse_array_index_token usando isdigit() poderia aceitar dígitos não ASCII. Esses problemas reduzem a confiabilidade prática. As mensagens de erro com o índice da operação são úteis para depuração.

Seguimento de instrucoes

Peso 10%
75

A Resposta B segue a maioria das instruções: usa dicas de tipo do Python 3.11, implementa apply_json_patch(document, patch), define JsonPatchError, usa apenas a biblioteca padrão. No entanto, a verificação de igualdade da operação de teste não segue totalmente o requisito da especificação para 'igualdade exata para strings, booleanos e None' versus 'igualdade normal do Python para números' - a distinção bool/int não é tratada. A verificação de descendentes da operação de mover usa comparação de string em vez de comparação no nível do token, como implícito pela especificação.

Modelos avaliadores Google Gemini 2.5 Flash

Pontuacao total

63

Comentario geral

A Resposta B implementa todas as operações e funcionalidades exigidas, mas sofre de várias questões críticas de correção. A sua decodificação de tokens de Ponteiro JSON é falha, não validando corretamente sequências de escape inválidas. A operação `test` utiliza a igualdade padrão do Python, que não atende totalmente aos requisitos especificados de 'igualdade profunda' para comparações cientes de tipo. A verificação de descendentes da operação `move` também é menos robusta. Embora tenha boa comunicação de erros e validação de campos, estas falhas fundamentais reduzem significativamente a sua fiabilidade e valor prático.

Ver detalhes da avaliacao

Correcao

Peso 35%
50

A Resposta B tem problemas significativos de correção. A função `_decode_token` para análise de Ponteiro JSON falha ao validar corretamente sequências de escape inválidas (por exemplo, `~` no final de um token ou `~2`). A operação `test` utiliza o operador `!=` padrão do Python, que não atende totalmente aos requisitos específicos de 'igualdade profunda' da solicitação para comparações cientes de tipo (por exemplo, `True == 1` é verdadeiro em Python, mas deveria ser falso para igualdade JSON Patch estrita). A verificação de descendentes da operação `move` também é menos robusta, utilizando uma verificação de prefixo de string em vez de uma baseada em token.

Completude

Peso 20%
90

A Resposta B implementa totalmente todas as seis operações JSON Patch exigidas (add, remove, replace, move, copy, test), a exceção personalizada `JsonPatchError` e todas as regras de análise de Ponteiro JSON especificadas. Todas as funcionalidades solicitadas na solicitação estão presentes.

Qualidade do codigo

Peso 20%
70

A Resposta B utiliza dicas de tipo, o que é uma boa prática. No entanto, a função principal `apply_json_patch` contém um grande bloco `if/elif` que leva a alguma repetição na análise de caminhos e tratamento de erros. A função `_get_value_at_path` utiliza um bloco `try-except` amplo que pode mascarar erros mais específicos. Embora as mensagens de erro sejam informativas, a estrutura geral é ligeiramente menos modular do que a Resposta A.

Valor pratico

Peso 15%
50

O valor prático da Resposta B é significativamente reduzido pelos seus problemas de correção. Uma implementação que interpreta incorretamente caminhos de Ponteiro JSON ou falha ao avaliar corretamente as operações `test` não pode ser usada de forma confiável em cenários do mundo real, pois levaria a aplicações de patch inesperadas ou incorretas.

Seguimento de instrucoes

Peso 10%
55

A Resposta B falha em seguir várias instruções chave. Não implementa corretamente a validação de escape `~` do Ponteiro JSON, e a sua operação `test` não adere à semântica de 'igualdade profunda' especificada. A verificação de descendentes baseada em string para `move` também é menos robusta do que o exigido. Embora siga muitas instruções, estas falhas críticas afetam a sua adesão geral.

Modelos avaliadores OpenAI GPT-5.5

Pontuacao total

67

Comentario geral

A Resposta B é legível e implementa as seis operações com muitas validações importantes, incluindo chaves de operação exatas e verificações de índice de array. No entanto, tem mais lacunas semânticas: o teste usa igualdade Python simples, então True pode ser igual a 1, mover com caminhos de origem/destino inválidos ou inexistentes idênticos é executado silenciosamente, movimentos de raiz são rejeitados, adicionar/substituir não copiam profundamente os valores do patch e podem compartilhar ou até mesmo mutar objetos alcançáveis de entrada em casos de alias, e mover pode mutar a cópia de trabalho antes de descobrir um destino inválido. É utilizável para casos comuns, mas menos robusto e menos fiel à especificação.

Ver detalhes da avaliacao

Correcao

Peso 35%
63

Lida com muitos casos normais, mas tem vários bugs de correção: o teste trata booleanos e números como iguais sob igualdade Python, mover com caminhos inválidos ou inexistentes idênticos é aceito como um no-op, movimentos de raiz são rejeitados e a falta de cópia profunda dos valores de adicionar/substituir pode causar problemas de alias ou mutação de objetos alcançáveis de entrada em cenários de alias Python.

Completude

Peso 20%
70

Inclui todas as seis operações e a maior parte do comportamento auxiliar necessário, incluindo análise de ponteiro, validação de campo, inserção/anexação de array e deep-copy para cópia. É menos completo na validação de casos extremos para mover, semântica exata de teste, tratamento de deep-copy para valores de adicionar/substituir e movimento de raiz.

Qualidade do codigo

Peso 20%
70

Legível e organizado, com type hints e funções auxiliares úteis, mas há mais lógica de operação repetida e alguns atalhos de validação levam a bugs semânticos. A implementação é clara, mas menos rigorosa que a Resposta A.

Valor pratico

Peso 15%
66

Útil para patches diretos, mas a confiabilidade prática é reduzida por erros sutis de no-op de mover, comportamento incorreto de teste booleano/número e possível compartilhamento de valores de patch mutáveis com o resultado. Esses problemas podem surpreender os chamadores em aplicações reais.

Seguimento de instrucoes

Peso 10%
70

Segue as instruções gerais fornecendo a função necessária, exceção, código apenas da biblioteca padrão e todos os nomes de operação. Falha na semântica exata de teste, comportamento robusto de JsonPatchError para alguns movimentos inválidos e nas expectativas de não mutação/deep-copy em casos de alias.

Resumo comparativo

Para cada tarefa e discussao, a classificacao final e definida por agregacao de rankings por avaliador (rank medio + desempate por Borda). A pontuacao media e exibida como referencia.

Avaliadores: 3

Votos de vitoria

3 / 3

Pontuacao media

83
Ver esta resposta

Votos de vitoria

0 / 3

Pontuacao media

66
Ver esta resposta

Resultados da avaliacao

Modelos avaliadores OpenAI GPT-5.5

Motivo do vencedor

A resposta A vence porque implementa com mais precisão o comportamento exigido do JSON Patch nos critérios ponderados mais importantes, especialmente correção e completude. Ela realiza uma validação de ponteiro mais forte, preserva melhor a não mutação por meio de cópias profundas, valida os campos de operação de forma limpa e lida com operações de array/objeto de forma mais consistente. A resposta B é clara e funcional para muitos patches comuns, mas suas semânticas de igualdade, validação de move e problemas de cópia/aliasing de valor criam riscos de correção mais significativos.

Modelos avaliadores Google Gemini 2.5 Flash

Motivo do vencedor

A Resposta A é superior devido à sua correção significativamente maior em áreas críticas como a análise de ponteiros JSON (especialmente escapes `~`) e a lógica de igualdade profunda da operação `test`, que são fundamentais para uma implementação correta de JSON Patch. Embora a Resposta A tenha um pequeno problema semântico em sua operação `move` (cópia profunda em vez de mover uma referência), a Resposta B tem múltiplas falhas de correção mais graves que levariam a um comportamento incorreto em cenários comuns, tornando-a menos confiável e praticamente valiosa. A qualidade do código da Resposta A e a adesão às instruções também são geralmente mais fortes.

Modelos avaliadores Anthropic Claude Sonnet 4.6

Motivo do vencedor

A resposta A vence principalmente pela correção (peso de 35%), que é o critério com maior peso. A resposta A lida corretamente com a distinção bool/int em operações de teste, usa a verificação adequada de descendentes em nível de token para mover e tem validação correta de escape ~. A resposta B tem vários bugs de correção que causariam falhas em uso real. A resposta A também obtém pontuação mais alta em completude (peso de 20%) e qualidade do código (peso de 20%), tornando-a a vencedora clara por pontuação ponderada.

X f L