2012-06-06 8 views
11

quiero serializar JSON a la siguiente (Java) estructura de datos:JSON Representación de mapa con complejo de Key

class Machine { 
    String name; 
    Map<PartDescriptor, Part> parts; 
} 

class PartDescriptor { 
    String group; 
    String id; 

    hashCode() 
    equals() 
} 

class Part { 
    String group; 
    String id; 
    String description; 
    String compat; 
    ... 
    ... 
} 

¿Cuál sería la representación JSON de una Machine?

también (opcional ), que me señale un JSON para Java serializador/deserializer que apoye su representación

+1

Debido JSON es tan limitado en su capacidad para expresar detalles de tipo, los serializadores de propósito general suelen ser frustrantes e inadecuados para fines específicos. Puede ser mucho más fácil implementar su propio serializador para sus propias estructuras de datos. – Pointy

+0

@Pointy Gracias Pointy, no he usado JSON para este tipo de propósito antes, y me di cuenta de tu punto. Hice esta pregunta para escuchar algunas ideas, ya que perdí algunas horas frustrantes con la api indocumentada y rara de jackson –

Respuesta

8

me gustaría hacer algo como:

{ 
    "name": "machine name", 
    "parts": [ 
    { "group": "part group", "id": "part id", "description": "...", ... }, 
    { "group": "part group", "id": "part id", "description": "...", ... }, 
    // ... 
    ] 
} 

Si el "id" para cada Parte es única, entonces la propiedad "partes" puede ser un objeto en lugar de una matriz, con el "id" de cada parte como clave.

{ 
    "name": "machine name", 
    "parts": { 
    "1st part id": { "group": "part group", "description": "...", ... }, 
    "2nd part id": { "group": "part group", "description": "...", ... }, 
    // ... 
    } 
} 
+0

Dado que PartDescriptor es la clave del mapa java, creo que podemos suponer con seguridad que la combinación grupo + id es única, así que ve con tu segunda muestra –

2

Haría esto. La clave parts del objeto de nivel superior sería JSONArray de JSONObject que tienen key y . El key sería un objeto que es su PartDescriptor y el value sería su Part.

{ 
    "name":"theName", 
    "parts":[ 
     { 
      "key":{ 
         "group":"theGroup", 
         "id":"theId" 
        }, 
      "value":{ 
         "group":"theGroup", 
         "id":"theId", 
         "description":"theDescription", 
         "compat":"theCompat", 
         ... 
        } 
     }, 
     ... 
    ] 
} 
1

Suponiendo que grupo + Identificación del ofrece una combinación única, y que ":" es un delimitador admisible:

{ 
    "name": "machine name", 
    "parts": { 
       "somegroup:01465": { 
            "group":"somegroup", 
            "id": "01465", 
            ... 
            }, 
       "othergroup:32409": { 
            "group":"othergroup", 
            "id": "32409", 
            ... 
            } 

      } 
} 
-4

Se puede traducirse por la siguiente tabla:

<table class="machine" name=""> 
    <tr> 
    <th class="partdescriptor" colspan="2"> 
    <th class="part" colspan="4"> 
    </tr> 
    <tr> 
    <td class="partdescriptor group"></td> 
    <td class="partdescriptor" id=""></td> 
    <td class="part group"></td> 
    <td class="part" id=""></td> 
    <td class="description"></td> 
    <td class="compat"></td> 
    </tr> 
</table> 

El marcado se descompone en el siguiente objeto JSON debido a la falta de metadatos a través de los atributos:

{ 
    "HTMLTableElement": 
    [ 
     { 
      "classname": "machine", 
      "name": "" 
     }, 
     { 
      "HTMLTableRowElement": 
      [ 
       { 
        "HTMLTableCellElement": {"classname":"partdescriptor","colspan":2} 
       }, 
       { 
        "HTMLTableCellElement": {"classname":"part","colspan":4} 
       } 
      ] 
     }, 
     { 
      "HTMLTableRowElement": 
      [ 
       { 
        "HTMLTableCellElement": {"classname":"partdescriptor group"} 
       }, 
       { 
        "HTMLTableCellElement": {"classname":"partdescriptor","id":""} 
       }, 
       { 
        "HTMLTableCellElement": {"classname":"part","id":""} 
       }, 
       { 
        "HTMLTableCellElement": {"classname":"description"} 
       }, 
       { 
        "HTMLTableCellElement": {"classname":"compat"} 
       } 
      ] 
     } 
    ] 
} 

Alternativamente, Unicode puede simplificar el mapeo:

{"name":"","[{\u0022group\u0022:\u0022\u0022},{\u0022id\u0022:\u0022\u0022}]": 
[ 
{"group":""}, 
{"id":""}, 
{"description":""}, 
{"compat":""} 
] 
} 

Que puede ser stringified:

JSON.stringify({"name":"","[{\u0022group\u0022:\u0022\u0022},{\u0022id\u0022:\u0022\u0022}":[{"group":""},{"id":""},{"description":""},{"compat":""}]}) 

para producir:

"{\"name\":\"\",\"[{\\\"group\\\":\\\"\\\"},{\\\"id\\\":\\\"\\\"}]\":[{\"group\":\"\"},{\"id\":\"\"},{\"description\":\"\"},{\"compat\":\"\"}]}" 

que puede ser analizada:

JSON.parse("{\"name\":\"\",\"[{\\\"group\\\":\\\"\\\"},{\\\"id\\\":\\\"\\\"}]\":[{\"group\":\"\"},{\"id\":\"\"},{\"description\":\"\"},{\"compat\":\"\"}]}") 

para producir un objeto literal:

Referencias

8

No es necesario Annot aciones o serializadores personalizados.Suponiendo que ya tiene getters para todos los campos en Part y Machine, todo lo que realmente falta es un toString() en PartDescriptor. Si, por alguna razón, no tiene funciones getter, tendrá que anotar los campos de interés con @JsonProperty para que Jackson sepa qué campos incluir en la salida serializada. Sin embargo, es preferible (y más fácil) simplemente crear getters.

El toString() en PartDescriptor debe devolver la clave que desea utilizar en su asignación. Como otra respuesta sugiere, es posible que simplemente concatenar los campos relevantes:

@Override 
public String toString() { 
    return group + "|" + id; 
} 

Después se le mágicamente obtenga este formulario cuando se intenta serializar un Machine con Jackson de ObjectMapper:

{ 
    "name" : "Toaster", 
    "parts" : { 
    "Electrical|Descriptor1" : { 
     "group" : "Electrical", 
     "id" : "Part1", 
     "description" : "Heating Element", 
     "compat" : "B293" 
    }, 
    "Exterior|Descriptor2" : { 
     "group" : "Exterior", 
     "id" : "Part2", 
     "description" : "Lever", 
     "compat" : "18A" 
    } 
    } 
} 
+0

El resultado es un objeto de JavaScript literal, pero no es un objeto JSON –

+0

@PaulSweatte ¿A qué te refieres? Este es [JSON válido] (http://jsonlint.com/). De hecho, todo JSON ** es ** un objeto de JavaScript literal ... – user113215

+0

Lo siento, mi copiar/pegar de su código se perdió un corchete. Sin embargo, la sintaxis JSON es más restrictiva que la sintaxis literal del objeto. Por ejemplo, no se permiten comentarios o comillas simples, y se deben citar los nombres de las teclas. –

Cuestiones relacionadas