在Java中将JSON类型转换为字节数组格式

39

使用UDP协议发送数据时,我遇到了一个问题,即当我尝试创建一个类型为JSON对象的数据时,无法获取我的数据的字节格式,以下是我的示例代码:

    JSONObject obj = new JSONObject();
    obj.put("name", "foo");
    obj.put("num", new Integer(100));
    obj.put("balance", new Double(1000.21));
    obj.put("is_vip", new Boolean(true));
    obj.put("nickname",null);

    sendData = obj.getBytes(); //this is error because not have methos getBytes();

我知道我的问题,但我不知道如何将JSON对象转换为字节,有什么建议吗?

4个回答

52
获取字符串的字节:
obj.toString().getBytes(theCharset);

3
调用 getBytes 方法时,应传入编码方式。否则会出现预期之外的编码问题,这会让事情不再有趣。 - user166390
请查看我的答案,了解如何避免不必要的转换为“String”以及基于提供的“charset”的额外编码:https://dev59.com/FGkw5IYBdhLWcg3wJXQh#39412196 - Stepan Vavra
JSONObject和String都是数据的不同表示形式。我们在记事本中看到的是JSON数据的字符串表示形式,而不是实际数据。例如,如果您在记事本中看到一个int值65535,这实际上是由字符6、5、5、3和5(五个字符= 5 * 2字节= 10字节在Java中)组成的字符串,而不是单个int值65535(在Java中为4个字节)。 - Manishoaham

34

假设你提到的JSONObject来自于这里,你可以按照以下方式获取字节

sendData = obj.toString().getBytes("utf-8");

是的,你说得对... :) 所以我每个答案都会放弃一些... :) - viyancs
@Agung,链接已失效,你能告诉我这个的用途是什么吗? - Derrick

3
为了避免不必要的从 String 转换为 byte[],并基于提供的 charset 强制进行编码,我更喜欢直接使用 JsonWriterByteArrayOutputStream(例如,JsonValue 子类型使用 JsonWriterStringWriter):
ByteArrayOutputStream stream = new ByteArrayOutputStream();
Json.createWriter(stream).write(obj);

byte[] sendData = stream.toByteArray()

System.out.println("Bytes array: " + sendData);
System.out.println("As a string: " + stream.toString());

此外,您还可以按照以下方式启用漂亮的打印功能:

(另外,pretty printing 是指将数据以易于阅读和美观的方式显示出来)

Json.createWriterFactory(
            Collections.singletonMap(JsonGenerator.PRETTY_PRINTING, true))
        .createWriter(stream)
        .write(obj);

唯一令人遗憾的是这不是一个单行代码。你至少需要3行代码(考虑到在此情况下省略调用JsonWriter.close()是不必要的)。

1
Json.createWriter(stream).write(obj);上述代码行仅接受Javax.json类型的obj,而不是问题中提到的JSONObject。如果您尝试像这样进行强制转换:Json.createWriter(stream).write((JSONObject)obj);它会抛出异常:无法转换。有关JSONObject类型对象的任何建议? - Sdembla
2
Json 来自哪里? - Harry Theo

3

使用jackson-databind项目的ObjectMapper实用程序类,例如objectMapper.writeValueAsBytes(dto)返回byte[]

@Autowired
private ObjectMapper objectMapper;

ContractFilterDTO filter = new ContractFilterDTO();
    mockMvc.perform(post("/api/customer/{ico}", "44077866")
            .contentType(MediaType.APPLICATION_JSON_UTF8_VALUE)
            .content(objectMapper.writeValueAsBytes(filter)))...

Maven依赖:

<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.8.8.1</version>
</dependency>

1
哦!我知道了,我错过了使用objectMapper...不过我已经更新了我的代码。谢谢。 - balajimore

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接