JSON Представление карты со сложным ключом

Я хочу сериализовать в JSON следующую структуру данных (java):

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

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

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

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

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

Ответ 2

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

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

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

Затем вы будете магически получать эту форму при попытке сериализации Machine с помощью Jackson 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"
    }
  }
}

Ответ 3

Я бы сделал это. Ключ 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",
                       ...
                    }
        },
        ...
    ]
}

Ответ 4

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

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

            }
}

Ответ 5

Он может отображаться как следующая таблица:

<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\":\"\"}]}")

для создания литерала объекта:

({name:"", '[{"group":""},{"id":""}]':[{group:""}, {id:""}, {description:""}, {compat:""}]})

Ссылки