2012-06-06 1 views
11

voglio serializzare a JSON seguente (Java) struttura dei dati:JSON Rappresentazione della Mappa con Complex chiave

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; 
    ... 
    ... 
} 

Quale potrebbe essere la rappresentazione JSON di una Machine?

anche (opzionale ), punto me un JSON a Java serializzatore/deserializzatore che sosterrà la vostra rappresentazione

+1

Perché JSON è così limitata nella sua capacità di esprimere dettagli di tipo, i serializzatori generici sono spesso frustranti e inadeguati per scopi specifici. Potrebbe essere molto più semplice implementare il proprio serializzatore per le proprie strutture dati. – Pointy

+0

@Pointy Grazie Pointy, non ho usato JSON per questo tipo di scopo prima e ho capito il tuo punto. Ho fatto questa domanda per ascoltare alcune idee visto che ho sprecato poche ore frustranti con l'api senza documenti e strano di Jackson –

risposta

8

mi piacerebbe fare qualcosa di simile:

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

Se il "id" per ogni Parte è unica, quindi la proprietà "parti" può essere un oggetto invece di una matrice, con l'"id" di ogni parte che serve come chiave.

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

Dato che PartDescriptor è la chiave della mappa java, penso che possiamo tranquillamente supporre che la combinazione di gruppo + id sia unica, quindi vai con il tuo secondo campione. –

2

Farei questo. La chiave parts dell'oggetto di livello superiore sarebbe un JSONArray di JSONObject con key e value. Il key sarebbe un oggetto che è il tuo PartDescriptor e lo value sarebbe il tuo Part.

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

Supponendo che gruppo + id dà una combinazione unica, e che ":" è un delimitatore ammesso:

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

      } 
} 
-4

Può essere reso come la seguente tabella:

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

Il markup si decompone nel seguente oggetto JSON a causa della mancanza di metadati tramite attributi:

{ 
    "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"} 
       } 
      ] 
     } 
    ] 
} 

In alternativa, Unicode può semplificare la mappatura:

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

Che può essere stringata:

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

produrre:

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

che può essere analizzato:

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

per produrre un oggetto letterale:

Riferimenti

8

Non è necessario annot azioni o serializzatori personalizzati.Supponendo che tu abbia già getter per tutti i campi in Part e Machine, tutto ciò che manca davvero è un toString() su PartDescriptor. Se, per qualche motivo, non si dispone di funzioni getter, è necessario annotare i campi di interesse con @JsonProperty in modo che Jackson sappia quali campi includere nell'output serializzato. Tuttavia, è preferibile (e più semplice) creare semplicemente getter.

Il toString() su PartDescriptor deve restituire la chiave che si desidera utilizzare nella mappatura. Come suggerisce un'altra risposta, si potrebbe semplicemente concatenare i campi rilevanti:

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

Poi ti magicamente ottiene questo modulo quando si tenta di serializzare un Machine con Jackson di 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

Il risultato è un oggetto JavaScript letterale, ma non un oggetto JSON –

+0

@PaulSweatte Che cosa intendi? Questo è [JSON valido] (http://jsonlint.com/). Infatti, tutto JSON ** è ** un oggetto JavaScript letterale ... – user113215

+0

Spiacente, la mia copia/incolla del tuo codice ha perso una parentesi. La sintassi JSON è tuttavia più restrittiva della sintassi letterale dell'oggetto. Ad esempio, non sono consentiti commenti o virgolette singole e i nomi delle chiavi devono essere citati. –

Problemi correlati