2012-06-06 4 views
11

Я хочу сериализации в JSON следующую (Java) структуры данных:JSON Представление карты с Complex 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; 
    ... 
    ... 
} 

Что бы JSON представление одного Machine?

Также (опция), указать мне на JSON в Java/десериализации сериализатора, которые будут поддерживать ваше представление

+1

Поскольку JSON является настолько ограниченным в его способности выражать детали типа, универсальные сериализаторы часто расстраивают и неадекватны для конкретных целей. Может быть намного проще реализовать собственный сериализатор для ваших собственных структур данных. – Pointy

+0

@Pointy Thanks Pointy, я раньше не использовал JSON для этой цели, и я понял вашу мысль. Я задал этот вопрос, чтобы услышать некоторые идеи, так как я потратил несколько разочаровывающих часов на недокументированное и незнакомое с Jackson api. –

ответ

8

Я хотел бы сделать что-то вроде:

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

Если "идентификатор" для каждая часть уникальна, то свойство «parts» может быть объектом вместо массива, а «id» каждой части служит в качестве ключа.

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

Поскольку PartDescriptor является ключом к java-карте, я думаю, мы можем с уверенностью предположить, что комбинация group + id уникальна, поэтому ваш второй образец. –

2

Я сделал бы это. Ключ parts объекта верхнего уровня будет JSONArray из JSONObject, которые имеют key и value. key будет объектом, который является вашим PartDescriptor, а value будет вашим Part.

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

Предполагая, что группа + идентификатор дает уникальную комбинацию, и что ":" является допустимым разделителем:

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

      } 
} 
-4

Это может быть вынесено в следующей таблице:

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

Разметка разлагается на следующий объект JSON из-за отсутствия метаданных через атрибуты:

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

В качестве альтернативы, Unicode, можно упростить отображение:

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

, который может быть строковой:

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

производить:

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

, который может быть проанализирован:

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

произвести литерал объекта:

Ссылки

8

Вам не нужно ANNOT или пользовательских сериализаторов.Предполагая, что у вас уже есть геттеры для всех полей в Part и Machine, все, что действительно отсутствует, это toString() на PartDescriptor. Если по какой-то причине у вас нет функций getter, вам нужно будет аннотировать интересующие поля @JsonProperty, поэтому Джексон знает, какие поля включать в сериализованный вывод. Однако предпочтительно (и проще) просто создавать геттеры.

toString() на PartDescriptor должен вернуть ключ, который вы хотите использовать в своем картографировании. Как подсказывает другой ответ, вы можете просто сцепить соответствующие поля:

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

Тогда вы будете волшебным образом получить эту форму, когда вы пытаетесь сериализовать Machine с Джексоном 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

Результатом является объект-объект JavaScript, но не объект JSON. –

+0

@PaulSweatte. Что вы имеете в виду? Это [действительный JSON] (http://jsonlint.com/). Фактически, все JSON ** являются ** объектным литералом JavaScript ... – user113215

+0

Извините, моя копия/вставка вашего кода пропустила скобку. Однако синтаксис JSON более строгий, чем синтаксис объектного литерала. Например, никакие комментарии или одинарные кавычки не разрешены, а ключевые имена должны быть указаны. –