2011-02-03 14 views
11

¿Hay alguna representación binaria compacta de JSON por ahí? Sé que hay BSON, pero incluso esa página web dice que "en muchos casos no es mucho más eficiente que JSON. En algunos casos, BSON usa incluso más espacio que JSON".representación binaria compacta de json

Estoy buscando un formato lo más compacto posible, preferiblemente algún tipo de estándar abierto?

+0

¿por qué no puede usar la compresión en el servidor? – Andrey

+1

Las especificaciones BSON están lejos de ser óptimas tanto en tamaño como en eficiencia. Tal vez deberías considerar almacenar JSON comprimido (con desinflar o algo así). – arthurprs

+0

@Andrey que puede ser una solución posible, pero estoy buscando para ver si hay una manera de reducir la cantidad de datos que alimentamos a la secuencia subyacente (que ya tiene una opción para hacer la compresión sobre la marcha). en teoría, debería ser más fácil comprimirlo en el nivel de codificación del objeto ya que tenemos contexto sobre las etiquetas, etc. –

Respuesta

7

Sí: Smile formato de datos. Es relativamente nuevo en cuanto a formatos de datos, tiene implementación pública de Java, la versión C está en proceso en github (libsmile). Tiene la ventaja de ser más compacto que JSON (confiablemente), pero al ser un modelo de datos lógicos 100% compatible, es fácil y posible convertir de un lado a otro con JSON textual.

Para el rendimiento, puede ver jvm-serializers punto de referencia, donde la sonrisa compite bien con otros formatos binarios (ahorro, avro, protobuf); Sizewise no es el más compacto (ya que conserva los nombres de los campos), pero lo hace mucho mejor con las secuencias de datos donde se repiten los nombres.

Está siendo utilizado por algunos proyectos (como Elastic Search, Protostuff-rpc lo admite), aunque no tan ampliamente como por ejemplo Thrift.

EDIT (dic 2011) - ahora también hay libsmile enlaces para PHP, Ruby y Python, por lo que el soporte de idiomas está mejorando. Además, hay medidas sobre el tamaño de los datos; y aunque para alternativas de datos de registro único (Avro, protobuf) son más compactas, para flujos de datos, la sonrisa a menudo es más compacta debido a la clave y la opción de referencia de valor de cadena.

+0

Sonrisa: especificaciones extrañas a pesar de los objetivos del proyecto. – arthurprs

+0

¿Cuidar para elaborar? Crítica constructiva bienvenida :) – StaxMan

+0

¡Gracias! esto es exactamente lo que estaba buscando –

3

gzipping Los datos JSON le proporcionarán buenas relaciones de compresión con muy poco esfuerzo debido a su soporte universal. Además, si se encuentra en un entorno de navegador, es posible que termine pagando un costo de bytes mayor en el tamaño de la dependencia de una biblioteca nueva que el que tendría con los ahorros en la carga real.

Si sus datos tienen restricciones adicionales (como muchos valores de campo redundantes), puede optimizar al mirar un protocolo de serialización diferente en lugar de apegarse a JSON. Ejemplo: una serialización basada en columnas como la de Avro upcoming columnar store puede obtener mejores proporciones (para el almacenamiento en disco). Si sus cargas contienen muchos valores constantes (como las columnas que representan las enumeraciones), también puede ser útil un enfoque de compresión del diccionario.

11

Puede echar un vistazo a Universal Binary JSON specification. No será tan compacto como Smile porque no hace referencias de nombres, pero es 100% compatible con JSON (donde como BSON y BJSON definen estructuras de datos que no existen en JSON, por lo que no hay una conversión estándar a/de).

También (intencionalmente) es criminalmente fácil de leer y escribir con un formato estándar de:

[type, 1-byte char]([length, 4-byte int32])([data]) 

tipos de datos tan simples comienzan con un código de marcador de ASCII como 'I' para un int de 32 bits, 'T' para verdadero, 'Z' para nulo, 'S' para cuerda y así sucesivamente.

El formato está diseñado por ingeniería para ser rápido de leer ya que todas las estructuras de datos tienen el prefijo de su tamaño por lo que no hay escaneo para las secuencias terminadas en nulo.

Por ejemplo, la lectura de una cadena que podría ser demarcada como esto (los -chars [] son ​​sólo para fines ilustrativos, que no están escritos en el formato)

[S][512][this is a really long 512-byte UTF-8 string....] 

verás la 'S' , enciéndalo para procesar una cadena, vea el entero de 4 bytes que lo sigue de "512" y sepa que puede simplemente tomar en un fragmento los siguientes 512 bytes y decodificarlos de nuevo a una cadena.

De forma similar, los valores numéricos se escriben sin un valor de longitud para ser más compactos porque su tipo (byte, int32, int64, doble) define su longitud de bytes (1, 4, 8 y 8 respectivamente. para números arbitrariamente largos que son extremadamente portátiles, incluso en plataformas que no los admiten).

En promedio, debería ver una reducción de tamaño de aproximadamente 30% con un objeto JSON bien equilibrado (muchos tipos mixtos). Si desea saber exactamente cómo ciertas estructuras se comprimen o no se comprimen, puede consultar la sección Size Requirements para tener una idea.

Por el lado positivo, independientemente de la compresión, los datos se escribirán en un formato más optimizado y serán más rápidos para trabajar.

Revisé el núcleo Input/OutputStream implementations para leer/escribir el formato en GitHub hoy. Verificaré el mapeo general de objetos basado en la reflexión más adelante esta semana.

Puede ver simplemente esas dos clases para ver cómo leer y escribir el formato, creo que la lógica central es algo así como 20 líneas de código. Las clases son más largas debido a las abstracciones de los métodos y a la estructuración de la verificación de los bytes del marcador para garantizar que el archivo de datos sea un formato válido; ese tipo de cosas.

Si tiene preguntas realmente específicas como la endianidad (grande) de la especificación o el formato numérico para dobles (IEEE 754), todo eso está cubierto en el documento de especificaciones o simplemente pregúnteme.

Espero que ayude!

+1

¡Esto es genial! El análisis es trivial. La velocidad es alta. El tamaño es muy bueno Y la representación se puede entender a través de 'tcpdump' (a diferencia de [varints] de protobuf (https://developers.google.com/protocol-buffers/docs/encoding#varints)). En hexadecimal simple, 300 es '0x012C'; en UBJ, '0x69012C' (ya que' 0x69' es ascii 'i'); en protobuf, '0xAC02 == 1010 1100 0000 0010'. Protobuf se vuelve aún más difícil (y más lento) para analizar si tienes números negativos. Protobuf no comprime cadenas o flotadores, así que a menos que tengas muchos enteros pequeños, el tamaño es similar, pero UBJ es rápido y su analizador es simple. – cdunn2001

+0

Cualquier punto de referencia publicado, números wrt velocidad? _Todo_ es rápido de analizar en estos días; debe comparar implementaciones para tener alguna idea de la velocidad real. – StaxMan

2

Otra alternativa que debe considerarse en estos días es CBOR (RFC 7049), que tiene un modelo explícitamente compatible con JSON con mucha flexibilidad. Es a la vez estable y cumple con su calificación de estándar abierto, y obviamente ha tenido mucho pensamiento puesto en ello.

+0

Muy bueno para ver un estándar real. ¡Gracias por la sugerencia! – Brad

Cuestiones relacionadas