Jackson ObjectMapper 如何将 byte[] 传输到 String 以及如何在没有对象类的情况下翻译它?
Posted
技术标签:
【中文标题】Jackson ObjectMapper 如何将 byte[] 传输到 String 以及如何在没有对象类的情况下翻译它?【英文标题】:How does Jackson ObjectMapper transfer byte[] to String and how can I translate it without object class? 【发布时间】:2017-02-22 16:49:17 【问题描述】:我想开发restful服务,它会返回JSON字符串给客户端。现在我的对象中有 byte[] 属性。
我使用 ObjectMapper 将此对象转换为 json 并响应客户端。 但是如果我使用 String.getBytes() 来翻译接收到的字符串,我发现 byte[] 是错误的。以下是示例。
Pojo 类
public class Pojo
private byte[] pic;
private String id;
//getter, setter,...etc
准备数据:使用图片获取字节数组
InputStream inputStream = FileUtils.openInputStream(new File("config/images.jpg"));
byte[] pic = IOUtils.toByteArray(inputStream);
Pojo pojo = new Pojo();
pojo.setId("1");
pojo.setPic(pic);
ObjectMapper mapper = new ObjectMapper();
String json = mapper.writeValueAsString(pojo);
--情况1:使用readvalue来object => image2.jpg是正确的
Pojo tranPojo = mapper.readValue(json, Pojo.class);
byte[] tranPicPojo = tranPojo.getPic();
InputStream isPojo = new ByteArrayInputStream(tranPicPojo);
File tranFilePojo = new File("config/images2.png");
FileUtils.copyInputStreamToFile(isPojo, tranFilePojo);
--情况2:使用readvalue映射得到String => image3.jpg坏了
Map<String, String> map = mapper.readValue(json, Map.class);
byte[] tranString = map.get("pic").getBytes();
InputStream isString = new ByteArrayInputStream(tranString);
File tranFileString = new File("config/images3.png");
FileUtils.copyInputStreamToFile(isString, tranFileString);
如果我必须使用情况 2 来翻译 JSON 字符串,我该怎么做?因为客户端无法获取 Pojo.class,所以客户端只能自己翻译 JSON 字符串。
非常感谢!
【问题讨论】:
不要使用文本来存储/传输二进制数据。new ObjectMapper().readValue(json, byte[].class)
【参考方案1】:
Jackson 正在将 byte[]
序列化为 Base64 字符串,如 the documentation of the serializer 中所述。
默认的 base64 变体是 MIME without line feed(所有内容都在一行中)。
您可以使用ObjectMapper
上的setBase64Variant
更改变体。
【讨论】:
非常感谢!我尝试添加以下语句并且保存的图像是正确的! Base64 base64 = new Base64(); byte[] tranString = base64.decode(map.get("pic").getBytes());【参考方案2】:ObjectMapper
处理这个,通过单元测试表示:
@Test
public void byteArrayToAndFromJson() throws IOException
final byte[] bytes = 1, 2, 3, 4, 5 ;
final ObjectMapper objectMapper = new ObjectMapper();
final byte[] jsoned = objectMapper.readValue(objectMapper.writeValueAsString(bytes), byte[].class);
assertArrayEquals(bytes, jsoned);
这是杰克逊 2.x 顺便说一句..
以下是使用 Jersey 将文件发送到浏览器的方法:
@GET
@Path("/documentFile")
@Produces("image/jpg")
public Response getFile()
final byte[] yourByteArray = ...;
final String yourFileName = ...;
return Response.ok(yourByteArray)
.header("Content-Disposition", "inline; filename=\"" + yourFilename + "\";")
.build();
另一个例子,使用 Spring MVC:
@RequestMapping(method = RequestMethod.GET)
public void getFile(final HttpServletResponse response)
final InputStream yourByteArrayAsStream = ...;
final String yourFileName = ...;
response.setContentType("image/jpg");
try
output = response.getOutputStream();
IOUtils.copy(yourByteArrayAsStream, output);
finally
IOUtils.closeQuietly(yourByteArrayAsStream);
IOUtils.closeQuietly(output);
【讨论】:
感谢您的回复。但是,如果前端 javascript 客户端调用此 API 来接收 JSON,他们是否可以在没有 ObjectMapper 的情况下正确地将 String 转换为 byte[]?此外,Jackson ObjectMapper 如何将 byte[] 转换为文本字符串?谢谢! 我看不出您的问题与 javascript 有什么关系?将文件发送到浏览器时,不会将其转换为字符串(包括 json)。您应该有一个单独的 url 来获取文件,并将其(或它的一个流)复制到响应中,并带有适当的标头(mime 类型等)。 因为我们将文件作为 byte[] 存储在 DB 中,我们必须选择它并响应前端以显示额外的信息(例如标题、描述...等)。所以我们一开始就尝试使用 JSON 来响应所有的信息。谢谢你的建议!我们将讨论这个解决方案。 你通常有两种方法,一种用于获取文件的元数据(标题、描述,可能是实际文件的 url),但不是文件本身。第二种方法是获取实际文件的方法。以上是关于Jackson ObjectMapper 如何将 byte[] 传输到 String 以及如何在没有对象类的情况下翻译它?的主要内容,如果未能解决你的问题,请参考以下文章
如何获取 Spring 4.1 使用的 Jackson ObjectMapper?
如何在不影响原始 bean 的“客户”的情况下声明另一个 Jackson ObjectMapper?