ruby on rails - Un texto JSON debe contener al menos dos octetos
ruby-on-rails irb (4)
Recibí este error y no pude encontrar ninguna respuesta razonable a esta pregunta, así que pensé en escribir un resumen del problema.
Si ejecuta este fragmento en irb:
JSON.parse( nil )
Verás el siguiente error:
TypeError: can''t convert nil into String
Esperaba que la función devolviera nil
, y no un TypeError
. Si convierte todas las entradas usando to_s
, verá el error de octeto:
JSON::ParserError: A JSON text must at least contain two octets!
Eso está bien y bien. Si no sabe qué es un octeto, lea esta publicación para obtener un resumen y una solución: ¿Qué es un octeto JSON y por qué se requieren dos?
Solución
La variable que estás pasando es una cadena vacía. No intente usar una cadena vacía en el método JSON.parse
.
Pregunta
Entonces, ahora que conozco la causa del error, ¿qué patrón debo usar para manejar esto? Estoy un poco reacio a parchear la biblioteca JSON para permitir valores nil
. Cualquier sugerencia sería muy apreciada.
Según json.org
JSON está construido sobre dos estructuras:
Una colección de pares de nombre / valor. En varios idiomas, esto se realiza como un objeto, registro, estructura, diccionario, tabla hash, lista con clave o matriz asociativa.
Una lista ordenada de valores. En la mayoría de los idiomas, esto se realiza como una matriz, vector, lista o secuencia.
Entonces, el mínimo de dos octetos (8 bits) requerido en el nivel superior sería {}
o []
En mi opinión, la mejor solución sería asegurarse de que el argumento de JSON.parse
sea un objeto estrigificado o una matriz estrigificada. :-)
data.presence && JSON.parse(data)
JSON.parse(data.presence || ''{}'')
hash = JSON.parse(json) rescue {}
array = JSON.parse(json) rescue []
string = JSON.parse(json) rescue ''''
parsed = json && json.length >= 2 ? JSON.parse(json) : nil
Pero realmente la biblioteca debería ser capaz de manejar este caso y devolver nil. Los navegadores web con soporte JSON incorporado parecen funcionar como espera después de todo.
O para hacerlo con un solo parche mini ligeramente intrusivo:
module JSON
def self.parse_nil(json)
JSON.parse(json) if json && json.length >= 2
end
end
parsed = JSON.parse_nil(json)