Как Jackson ObjectMapper передает байт [] в строку и как я могу перевести его без класса объекта?

#java #arrays #json #jackson #objectmapper

#java #массивы #json #джексон #объектный преобразователь

Вопрос:

Я хотел бы разработать restful service, и он вернет клиенту строку JSON. Теперь в моем объекте есть атрибут byte[] .

Я использую ObjectMapper для перевода этого объекта в json и ответа клиенту. Но я нахожу, что байт [] неверен, если я использую String.getBytes() для перевода полученной строки. Ниже приведен пример.

Класс 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 => the 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 => the 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.

Большое спасибо!

Комментарии:

1. Не используйте текст для хранения / передачи двоичных данных.

2. new ObjectMapper().readValue(json, byte[].class)

Ответ №1:

Джексон byte[] сериализуется как строка Base64, как описано в документации сериализатора.

Вариант base64 по умолчанию — это MIME без перевода строки (все в одной строке).

Вы можете изменить вариант, используя setBase64Variant на ObjectMapper .

Комментарии:

1. Большое спасибо! Я пытаюсь добавить следующие инструкции, и сохраненное изображение правильное! 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);
}
 

Кстати, это jackson 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);
    }
}
 

Комментарии:

1. Спасибо за ваш ответ. Но если клиенты javascript с открытым исходным кодом вызывают этот API для получения JSON, могут ли они правильно перевести строку в byte[] без ObjectMapper? Кроме того, как Jackson ObjectMapper переводит байт [] в текстовую строку? Спасибо!

2. Я не вижу, чтобы ваш вопрос имел какое-либо отношение к javascript? При отправке файла в браузер он не преобразуется в строку (включая json). У вас должен быть отдельный URL-адрес для получения файла, и скопируйте его (или его поток) в ответ с соответствующими заголовками (mime-тип и так далее).

3. Поскольку мы храним файл как byte[] в БД, мы должны выбрать его и ответить на frond-end для отображения с дополнительной информацией (например, заголовок, описание … и т.д.). Итак, мы пытаемся использовать JSON для ответа на всю информацию в начале. Спасибо за ваше предложение! Мы обсудим это решение.

4. Тогда у вас обычно будет 2 метода, один для получения метаданных для файла (название, описание, возможно, URL-адрес фактического файла), но не сам файл. Второй метод будет использоваться для извлечения фактического файла.