JavaScript Python PHP
import * as __biblioteca0 from "yaml";
function executar(input = '{"nome":"João","idade":25}', required = true) {
const { validateJson: validateJson } = (() => {
function validateJson(input) {
if (!input.trim())
throw new Error('Informe um documento JSON.');
if (input.length > 1000000)
throw new Error('Limite: 1 milhão de caracteres.');
try {
// Syntax only. Never use these parsed numbers to produce the formatted output.
JSON.parse(input);
}
catch (cause) {
const message = cause instanceof Error ? cause.message : 'Erro de sintaxe';
const offset = message.match(/position (\d+)/i);
const nativeLocation = message.match(/line (\d+) column (\d+)/i);
const position = offset ? Math.min(Number(offset[1]), input.length) : /end of JSON/i.test(message) ? input.length : undefined;
const before = position === undefined ? undefined : input.slice(0, position);
const line = before === undefined ? nativeLocation?.[1] : String(before.split('\n').length);
const column = before === undefined ? nativeLocation?.[2] : String(before.length - before.lastIndexOf('\n'));
const location = line && column ? ` (linha ${line}, coluna ${column})` : '';
throw new Error(`JSON inválido${location}: ${message}`);
}
const first = input.trim()[0];
const type = first === '{' ? 'objeto' : first === '[' ? 'lista' : first === '"' ? 'string' : first === 'n' ? 'null' : first === 't' || first === 'f' ? 'booleano' : 'número';
return { valid: true, type };
}
return { validateJson: validateJson };
})();
const { parseJsonCompatible: parseJsonCompatible } = (() => {
const LineCounter = __biblioteca0["LineCounter"];
const parseDocument = __biblioteca0["parseDocument"];
const isAlias = __biblioteca0["isAlias"];
const isScalar = __biblioteca0["isScalar"];
const isSeq = __biblioteca0["isSeq"];
const isMap = __biblioteca0["isMap"];
const SAFE_TAGS = new Set(['str', 'bool', 'null', 'int', 'float', 'map', 'seq'].map(tag => `tag:yaml.org,2002:${tag}`));
function parseJsonCompatible(input, format, onObjectKeys) {
if (!input.trim())
throw new Error(`Informe um documento ${format}.`);
if (input.length > 1000000)
throw new Error('A entrada excede o limite de 1 milhão de caracteres.');
if (format === 'JSON') {
// Syntax check only: do not use the rounded numeric values from JSON.parse.
try {
JSON.parse(input);
}
catch (cause) {
throw new Error(`JSON inválido: ${cause instanceof Error ? cause.message : 'erro de sintaxe'}`);
}
}
const lines = new LineCounter();
const doc = parseDocument(input, { version: '1.2', schema: format === 'JSON' ? 'json' : 'core', intAsBigInt: true, uniqueKeys: true, lineCounter: lines, prettyErrors: true, resolveKnownTags: false });
const issue = doc.errors[0] ?? doc.warnings[0];
if (issue)
throw new Error(`${format} inválido (${issue.code}): ${issue.message}`);
if (doc.directives?.yaml.version !== '1.2')
throw new Error('Somente YAML 1.2 é aceito para preservar os tipos de JSON.');
let count = 0;
function fail(message, node) {
const offset = node?.range?.[0];
const position = offset === undefined ? '' : (() => { const { line, col } = lines.linePos(offset); return ` (linha ${line}, coluna ${col})`; })();
throw new Error(message + position);
}
function convert(node, depth = 0) {
if (++count > 100000 || depth > 100)
fail('Documento muito complexo: limite de 100 níveis ou 100 mil nós.', node);
if (!node)
return null;
if (isAlias(node))
fail('Aliases YAML não são aceitos: JSON não preserva referências ou ciclos.', node);
if (node.tag && !SAFE_TAGS.has(node.tag))
fail(`Tag não permitida: ${node.tag}.`, node);
if (isScalar(node)) {
const value = node.value;
if (typeof value === 'bigint') {
if (value === BigInt(0) && node.source?.startsWith('-'))
fail('JSON de saída não preserva o sinal de zero negativo. Use 0 ou uma string.', node);
if (value > BigInt(Number.MAX_SAFE_INTEGER) || value < BigInt(Number.MIN_SAFE_INTEGER))
fail('Inteiro fora do intervalo seguro de JSON/JavaScript. Use uma string entre aspas para preservar todos os dígitos.', node);
return Number(value);
}
if (typeof value === 'number') {
if (!Number.isFinite(value))
fail('JSON não representa NaN ou infinito.', node);
if (Number.isInteger(value) && !Number.isSafeInteger(value))
fail('Número inteiro fora do intervalo seguro. Use uma string entre aspas para preservar a precisão.', node);
if (value === 0 && /[1-9]/.test((node.source ?? '').split(/[eE]/)[0]))
fail('Número pequeno demais para a precisão de JavaScript. Use uma string entre aspas.', node);
if (Object.is(value, -0))
fail('JSON de saída não preserva o sinal de zero negativo. Use 0 ou uma string.', node);
return value;
}
if (value === null || typeof value === 'string' || typeof value === 'boolean')
return value;
fail('Valor não representável em JSON.', node);
}
if (isSeq(node))
return node.items.map(item => convert(item, depth + 1));
if (isMap(node)) {
const result = Object.create(null);
const keys = [];
for (const pair of node.items) {
if (!isScalar(pair.key) || typeof pair.key.value !== 'string')
fail('Chaves de objetos devem ser strings; chaves numéricas, booleanas ou complexas não são preservadas em JSON.', pair.key);
const key = pair.key.value;
if (format === 'YAML' && key === '<<' && pair.key.type === 'PLAIN')
fail('Chaves de merge YAML (<<) não são aceitas.', pair.key);
if (Object.hasOwn(result, key))
fail(`Chave duplicada: ${key}.`, pair.key);
keys.push(key);
result[key] = convert(pair.value, depth + 1);
}
onObjectKeys?.(result, keys);
return result;
}
fail('Estrutura não representável em JSON.', node);
}
if (!doc.contents)
throw new Error('Informe um documento com um valor; use null para um valor nulo.');
return convert(doc.contents);
}
return { parseJsonCompatible: parseJsonCompatible };
})();
const SCHEMA_DIALECT = 'http://json-schema.org/draft-07/schema#';
function read(input, label) {
try {
if (input.length > 100000)
throw new Error('Limite de 100 mil caracteres por entrada.');
validateJson(input);
return parseJsonCompatible(input, 'JSON');
}
catch (cause) {
throw new Error(`${label}: ${cause instanceof Error ? cause.message : 'entrada inválida'}`);
}
}
function generateJsonSchema(input, required = true) {
if (typeof required !== 'boolean')
throw new Error('A opção de propriedades obrigatórias deve ser booleana.');
const data = read(input, 'Exemplo JSON');
function infer(value) {
if (value === null)
return { type: 'null' };
if (Array.isArray(value)) {
const variants = new Map();
for (const item of value) {
const schema = infer(item);
variants.set(JSON.stringify(schema), schema);
if (variants.size > 100)
throw new Error('Limite de 100 estruturas distintas por lista.');
}
const items = variants.size === 0 ? {} : variants.size === 1 ? [...variants.values()][0] : { anyOf: [...variants.values()] };
return { type: 'array', items };
}
if (typeof value === 'object') {
const properties = Object.create(null);
for (const key of Object.keys(value)) {
if (key === '__proto__')
throw new Error('A biblioteca não suporta declarar __proto__ em properties. A geração foi interrompida para não omitir sua regra.');
properties[key] = infer(value[key]);
}
const schema = { type: 'object', properties };
if (required && Object.keys(value).length)
schema.required = Object.keys(value);
return schema;
}
return { type: typeof value === 'number' ? Number.isInteger(value) ? 'integer' : 'number' : typeof value };
}
const output = JSON.stringify({ $schema: SCHEMA_DIALECT, ...infer(data) }, null, 2);
if (output.length > 1000000)
throw new Error('O schema gerado excede 1 milhão de caracteres.');
return output;
}
return generateJsonSchema(input, required);
}
import json
import math
def executar(input='{"nome":"João","idade":25}', required=True):
def read(text):
if not text.strip(): raise ValueError('Informe um documento JSON')
if len(text.encode('utf-16-le',errors='surrogatepass'))//2>100000: raise ValueError('Limite de 100 mil caracteres')
def pairs(items):
output={}
for key,value in items:
if key in output: raise ValueError('Chave duplicada: '+key)
output[key]=value
return output
def number(token):
value=float(token) if '.' in token or 'e' in token.lower() else int(token)
if not math.isfinite(value): raise ValueError('Número não finito')
if value==0 and (token.startswith('-') or any(c in '123456789' for c in token.lower().split('e')[0])): raise ValueError('Zero negativo ou underflow')
if value%1==0 and abs(value)>9007199254740991: raise ValueError('Inteiro fora do intervalo seguro; use string')
return value
def reject(value): raise ValueError('Constante JSON inválida: '+value)
value=json.loads(text,object_pairs_hook=pairs,parse_int=number,parse_float=number,parse_constant=reject)
count=0
def walk(value,depth=0):
nonlocal count
count+=1
if count>100000 or depth>100: raise ValueError('Limite de 100 níveis ou 100 mil nós')
if isinstance(value,dict):
for child in value.values(): walk(child,depth+1)
elif isinstance(value,list):
for child in value: walk(child,depth+1)
walk(value)
return value
if type(required) is not bool: raise ValueError('Opção inválida')
def reject(value): raise ValueError('Constante inválida: ' + value)
value = read(input)
def infer(value):
if value is None: return {'type':'null'}
if type(value) is bool: return {'type':'boolean'}
if isinstance(value, str): return {'type':'string'}
if isinstance(value, (int, float)): return {'type':'integer' if value % 1 == 0 else 'number'}
if isinstance(value, list):
variants = {}
for item in value:
schema = infer(item)
variants[json.dumps(schema, sort_keys=True)] = schema
if len(variants)>100: raise ValueError('Limite de 100 estruturas distintas')
items = {} if not variants else next(iter(variants.values())) if len(variants) == 1 else {'anyOf':list(variants.values())}
return {'type':'array', 'items':items}
if '__proto__' in value: raise ValueError('__proto__ não suportado em properties')
schema = {'type':'object','properties':{key:infer(item) for key,item in value.items()}}
if required and value: schema['required'] = list(value)
return schema
output = json.dumps({'$schema':'http://json-schema.org/draft-07/schema#', **infer(value)}, ensure_ascii=False, indent=2)
if len(output.encode('utf-16-le',errors='surrogatepass'))//2>1000000: raise ValueError('Schema gerado excede 1 milhão de caracteres')
return output
<?php
function executar($input = '{"nome":"João","idade":25}', $required = true) {
$read = function ($text) {
if (trim($text)==='') throw new InvalidArgumentException('Informe um documento JSON');
if (!function_exists('iconv')) throw new RuntimeException('Requer extensão iconv');
$utf16=iconv('UTF-8','UTF-16LE',$text);
if ($utf16===false || strlen($utf16)/2>100000) throw new InvalidArgumentException('UTF-8 inválido ou limite de entrada excedido');
json_decode($text,false,512,JSON_THROW_ON_ERROR | JSON_BIGINT_AS_STRING);
$stack=[];
for ($i=0;$i<strlen($text);$i++) {
$ch=$text[$i];
if ($ch==='{' || $ch==='[') { $stack[]=['object'=>$ch==='{','keys'=>[]]; continue; }
if ($ch==='}' || $ch===']') { array_pop($stack); continue; }
if ($ch==='"') {
$start=$i; $escaped=false;
while (++$i<strlen($text)) { $c=$text[$i]; if ($escaped) $escaped=false; elseif ($c==='\\') $escaped=true; elseif ($c==='"') break; }
$look=$i+1; while ($look<strlen($text) && str_contains(" \t\r\n",$text[$look])) $look++;
$index=count($stack)-1;
if ($index>=0 && $stack[$index]['object'] && ($text[$look] ?? '')===':') {
$key=json_decode(substr($text,$start,$i-$start+1),false,512,JSON_THROW_ON_ERROR);
if (array_key_exists($key,$stack[$index]['keys'])) throw new InvalidArgumentException('Chave duplicada: '.$key);
$stack[$index]['keys'][$key]=true;
}
} elseif ($ch==='-' || ctype_digit($ch)) {
preg_match('/\G-?(?:0|[1-9][0-9]*)(?:\.[0-9]+)?(?:[eE][+-]?[0-9]+)?/',$text,$match,0,$i);
$token=$match[0]; $number=(float)$token; $mantissa=explode('e',strtolower($token))[0];
if (!is_finite($number) || ($number==0 && (str_starts_with($token,'-') || preg_match('/[1-9]/',$mantissa))) || (floor($number)===$number && abs($number)>9007199254740991)) throw new InvalidArgumentException('Número não preservável; use string');
$i+=strlen($token)-1;
}
}
$value=json_decode($text,false,512,JSON_THROW_ON_ERROR);
$count=0;
$walk=function ($value,$depth=0) use (&$walk,&$count) { if (++$count>100000 || $depth>100) throw new InvalidArgumentException('Limite de 100 níveis ou 100 mil nós'); if (is_object($value) || is_array($value)) foreach ($value as $child) $walk($child,$depth+1); };
$walk($value);
return $value;
};
if (!is_bool($required)) throw new InvalidArgumentException('Opção inválida');
$value = $read($input);
$infer = function ($value) use (&$infer, $required) {
if ($value === null) return ['type'=>'null'];
if (is_bool($value)) return ['type'=>'boolean'];
if (is_string($value)) return ['type'=>'string'];
if (is_int($value) || is_float($value)) return ['type'=>floor($value) == $value ? 'integer' : 'number'];
if (is_array($value)) {
$variants = [];
foreach ($value as $item) { $schema = $infer($item); $variants[json_encode($schema, JSON_THROW_ON_ERROR)] = $schema; }
if (count($variants)>100) throw new InvalidArgumentException('Limite de 100 estruturas distintas');
$items = count($variants) === 0 ? (object)[] : (count($variants) === 1 ? reset($variants) : ['anyOf'=>array_values($variants)]);
return ['type'=>'array','items'=>$items];
}
if (property_exists($value,'__proto__')) throw new InvalidArgumentException('__proto__ não suportado em properties');
$properties = new stdClass();
foreach (get_object_vars($value) as $key=>$item) $properties->{$key} = $infer($item);
$schema = ['type'=>'object','properties'=>$properties];
if ($required && count(get_object_vars($value))) $schema['required'] = array_keys(get_object_vars($value));
return $schema;
};
$output = json_encode(array_merge(['$schema'=>'http://json-schema.org/draft-07/schema#'], $infer($value)), JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_THROW_ON_ERROR);
$output=preg_replace_callback('/^( +)/m',fn($match)=>str_repeat(' ',strlen($match[1])/2),$output);
if (strlen(iconv('UTF-8','UTF-16LE',$output))/2>1000000) throw new InvalidArgumentException('Schema gerado excede 1 milhão de caracteres');
return $output;
}