19

我想将以下(java)数据结构序列化为 JSON:

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

one 的 JSON 表示形式是Machine什么?

另外(可选),将我指向一个 JSON 到 Java 序列化器/反序列化器,它将支持您的表示

4

6 回答 6

14

我会做类似的事情:

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

如果每个 Part 的“id”是唯一的,那么“parts”属性可以是对象而不是数组,每个部分的“id”作为键。

{
  "name": "machine name",
  "parts": {
     "1st part id": { "group": "part group", "description": "...", ... },
     "2nd part id": { "group": "part group", "description": "...", ... },
     // ...
  }
}
于 2012-06-06T12:21:49.537 回答
10

您不需要注释或自定义序列化程序。假设您已经为PartandMachine中的所有字段设置了 getter,那么真正缺少的只是toString()on PartDescriptor。如果出于某种原因,您没有 getter 函数,则需要对感兴趣的字段进行注释,@JsonProperty以便 Jackson 知道要包含在序列化输出中的字段。但是,最好(也更容易)简单地创建 getter。

toString()onPartDescriptor应该返回您要在映射中使用的键。正如另一个答案所暗示的,您可以简单地连接相关字段:

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

然后,当您尝试Machine用 Jackson's序列化 a 时,您会神奇地得到这种形式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"
    }
  }
}
于 2013-08-17T03:22:19.577 回答
4

我会这样做。parts顶级对象的键将JSONArrayJSONObject具有key's 和value's 的一个。thekey将是您的对象,PartDescriptor而 thevalue将是您的Part.

{
    "name":"theName",
    "parts":[
        {
            "key":{
                       "group":"theGroup",
                       "id":"theId"
                  },
            "value":{
                       "group":"theGroup",
                       "id":"theId",
                       "description":"theDescription",
                       "compat":"theCompat",
                       ...
                    }
        },
        ...
    ]
}
于 2012-06-06T12:22:16.603 回答
1

假设 group+id 给出了一个唯一的组合,并且 ":" 是一个允许的分隔符:

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

            }
}
于 2012-06-06T12:42:08.700 回答
0

JSON 要求密钥是一个字符串,因此如果您确实需要将数据表示为键控(例如,您不想使用数组,就像 Pointy 的回答中那样,因为您想在合同中保证它没有具有相同键的重复条目),那么您需要自行决定将复杂键序列化为字符串的方法。

group1|part1如果使用使用分隔符连接的方法(例如),需要注意两点:

  • 您需要一个本身不能出现在关键部分中的分隔符,或者在序列化时需要对其进行转义(例如将其加倍)。这防止的问题可能很少遇到,但如果要以可重用的通用代码编写,则最好根据墨菲定律保证它 - 如果出现问题,最终会出现问题。
  • 为了真正防止“具有相同复合键的多个值”,您需要保持键的相同顺序,例如按字母顺序对键进行排序

鉴于:

另外(可选),将我指向一个 JSON 到 Java 序列化器/反序列化器,它将支持您的表示

一个值得注意的例子可能是Gson - Google 的 Java 的 JSON 序列化程序库 - 它使用这种表示:

{
     "(group1,part1)": { description: ... },
     "(group1,part2)": { description: ... },
     "(group2,part1)": { description: ... },
     ...
     "(groupX,partX)": {description: ... },
}

注意:该功能需要通过设置启用(为了向后兼容enableComplexMapKeySerialization默认关闭)

于 2019-12-16T13:04:23.920 回答
-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:""}]})

参考

于 2013-08-16T16:31:53.553 回答