- How to convert a JSON string to a Map with Jackson JSON
- 11 Answers 11
- Введение в Jackson ObjectMapper
- 2. Зависимости
- 3. Чтение и запись с помощью ObjectMapper
- 3.1. Объект Java в JSON
- 3.2. JSON в объект Java
- 3.3. JSON в Джексон JsonNode
- 3.4. Создание списка Java из строки массива JSON
- 3.5. Создание карты Java из строки JSON
- 4. Расширенные функции
- 4.1. Настройка функции сериализации или десериализации
- 4.2. Создание пользовательского сериализатора или десериализатора
- 4.3. Обработка форматов даты
- 4.4. Обработка коллекций
- 5. Вывод
How to convert a JSON string to a Map with Jackson JSON
What’s the right way to do this? I’m only using Jackson because that’s what is already available in the project, is there a native Java way of converting to/from JSON? In PHP I would simply json_decode($str) and I’d get back an array. I need basically the same thing here.
It’s our wrapper for Jackson, handles some of the JsonFactory and ObjectMapper stuff that you have to do.
The title has nothing to do with your described problem, which has to do with untyped collection. The answer below is the correct answer to what you really tried to ask.
11 Answers 11
[Update Sept 2020] Although my original answer here, from many years ago, seems to be helpful and is still getting upvotes, I now use the GSON library from Google, which I find to be more intuitive.
I’ve got the following code:
public void testJackson() throws IOException < ObjectMapper mapper = new ObjectMapper(); File from = new File("albumnList.txt"); TypeReference> typeRef = new TypeReference>() <>; HashMap o = mapper.readValue(from, typeRef); System.out.println("Got " + o); >
It’s reading from a file, but mapper.readValue() will also accept an InputStream and you can obtain an InputStream from a string by using the following:
new ByteArrayInputStream(astring.getBytes("UTF-8"));
There’s a bit more explanation about the mapper on my blog.
Введение в Jackson ObjectMapper
В этом руководстве основное внимание уделяется пониманию класса Jackson ObjectMapper и тому, как сериализовать объекты Java в JSON и десериализовать строку JSON в объекты Java.
Чтобы узнать больше о библиотеке Джексона в целом, можно начать с учебника по Джексону .
2. Зависимости
Давайте сначала добавим в pom.xml следующие зависимости :
dependency> groupId>com.fasterxml.jackson.coregroupId> artifactId>jackson-databindartifactId> version>2.13.0version> dependency>
Эта зависимость также транзитивно добавит в путь к классам следующие библиотеки:
Всегда используйте последние версии из центрального репозитория Maven для jackson-databind .
3. Чтение и запись с помощью ObjectMapper
Начнем с основных операций чтения и записи.
Простой API readValue ObjectMapper — хорошая отправная точка. Мы можем использовать его для анализа или десериализации содержимого JSON в объект Java.
Кроме того, на стороне записи мы можем использовать API writeValue для сериализации любого объекта Java в виде вывода JSON.
В этой статье мы будем использовать следующий класс Car с двумя полями в качестве объекта для сериализации или десериализации:
public class Car private String color; private String type; // standard getters setters >
3.1. Объект Java в JSON
Давайте посмотрим на первый пример сериализации объекта Java в JSON с использованием метода writeValue класса ObjectMapper :
ObjectMapper objectMapper = new ObjectMapper(); Car car = new Car("yellow", "renault"); objectMapper.writeValue(new File("target/car.json"), car);
Вывод вышеуказанного в файле будет:
Методы writeValueAsString и writeValueAsBytes класса ObjectMapper генерируют JSON из объекта Java и возвращают сгенерированный JSON в виде строки или массива байтов:
String carAsString = objectMapper.writeValueAsString(car);
3.2. JSON в объект Java
Ниже приведен простой пример преобразования строки JSON в объект Java с использованием класса ObjectMapper :
String json = "< \"color\" : \"Black\", \"type\" : \"BMW\" >"; Car car = objectMapper.readValue(json, Car.class);
Функция readValue() также принимает другие формы ввода, например файл, содержащий строку JSON:
Car car = objectMapper.readValue(new File("src/test/resources/json_car.json"), Car.class);
Car car = objectMapper.readValue(new URL("file:src/test/resources/json_car.json"), Car.class);
3.3. JSON в Джексон JsonNode
В качестве альтернативы JSON можно преобразовать в объект JsonNode и использовать для извлечения данных из определенного узла:
String json = "< \"color\" : \"Black\", \"type\" : \"FIAT\" >"; JsonNode jsonNode = objectMapper.readTree(json); String color = jsonNode.get("color").asText(); // Output: color -> Black
3.4. Создание списка Java из строки массива JSON
Мы можем разобрать JSON в виде массива в список объектов Java, используя TypeReference :
String jsonCarArray = "[< \"color\" : \"Black\", \"type\" : \"BMW\" >, < \"color\" : \"Red\", \"type\" : \"FIAT\" >]"; ListCar> listCar = objectMapper.readValue(jsonCarArray, new TypeReferenceListCar>>()>);
3.5. Создание карты Java из строки JSON
Точно так же мы можем разобрать JSON в карту Java :
String json = "< \"color\" : \"Black\", \"type\" : \"BMW\" >"; MapString, Object> map = objectMapper.readValue(json, new TypeReferenceMapString,Object>>()>);
4. Расширенные функции
Одной из самых сильных сторон библиотеки Джексона является настраиваемый процесс сериализации и десериализации.
В этом разделе мы рассмотрим некоторые дополнительные функции, в которых входной или выходной ответ JSON может отличаться от объекта, который создает или использует ответ.
4.1. Настройка функции сериализации или десериализации
При преобразовании объектов JSON в классы Java, если в строке JSON есть новые поля, процесс по умолчанию приведет к исключению:
Строка JSON в приведенном выше примере в процессе синтаксического анализа по умолчанию для объекта Java для класса Car приведет к исключению UnrecognizedPropertyException .
С помощью метода configure мы можем расширить процесс по умолчанию, чтобы игнорировать новые поля :
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); Car car = objectMapper.readValue(jsonString, Car.class); JsonNode jsonNodeRoot = objectMapper.readTree(jsonString); JsonNode jsonNodeYear = jsonNodeRoot.get("year"); String year = jsonNodeYear.asText();
Еще один вариант основан на FAIL_ON_NULL_FOR_PRIMITIVES , который определяет, разрешены ли нулевые значения для примитивных значений:
objectMapper.configure(DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES, false);
Аналогично, FAIL_ON_NUMBERS_FOR_ENUM определяет, разрешено ли сериализовать/десериализовать значения перечисления как числа:
objectMapper.configure(DeserializationFeature.FAIL_ON_NUMBERS_FOR_ENUMS, false);
Вы можете найти полный список функций сериализации и десериализации на официальном сайте .
4.2. Создание пользовательского сериализатора или десериализатора
Еще одной важной функцией класса ObjectMapper является возможность регистрации собственного сериализатора и десериализатора .
Пользовательские сериализаторы и десериализаторы очень полезны в ситуациях, когда входной или выходной ответ JSON отличается по структуре от класса Java, в который он должен быть сериализован или десериализован.
Ниже приведен пример пользовательского сериализатора JSON :
public class CustomCarSerializer extends StdSerializerCar> public CustomCarSerializer() this(null); > public CustomCarSerializer(ClassCar> t) super(t); > @Override public void serialize( Car car, JsonGenerator jsonGenerator, SerializerProvider serializer) jsonGenerator.writeStartObject(); jsonGenerator.writeStringField("car_brand", car.getType()); jsonGenerator.writeEndObject(); > >
Этот пользовательский сериализатор можно вызвать следующим образом:
ObjectMapper mapper = new ObjectMapper(); SimpleModule module = new SimpleModule("CustomCarSerializer", new Version(1, 0, 0, null, null, null)); module.addSerializer(Car.class, new CustomCarSerializer()); mapper.registerModule(module); Car car = new Car("yellow", "renault"); String carJson = mapper.writeValueAsString(car);
Вот как выглядит Car (как вывод JSON) на стороне клиента:
var carJson = "car_brand":"renault">
А вот пример пользовательского десериализатора JSON :
public class CustomCarDeserializer extends StdDeserializerCar> public CustomCarDeserializer() this(null); > public CustomCarDeserializer(Class?> vc) super(vc); > @Override public Car deserialize(JsonParser parser, DeserializationContext deserializer) Car car = new Car(); ObjectCodec codec = parser.getCodec(); JsonNode node = codec.readTree(parser); // try catch block JsonNode colorNode = node.get("color"); String color = colorNode.asText(); car.setColor(color); return car; > >
Этот пользовательский десериализатор можно вызвать следующим образом:
String json = "< \"color\" : \"Black\", \"type\" : \"BMW\" >"; ObjectMapper mapper = new ObjectMapper(); SimpleModule module = new SimpleModule("CustomCarDeserializer", new Version(1, 0, 0, null, null, null)); module.addDeserializer(Car.class, new CustomCarDeserializer()); mapper.registerModule(module); Car car = mapper.readValue(json, Car.class);
4.3. Обработка форматов даты
Сериализация java.util.Date по умолчанию создает число, т. е. отметку времени эпохи (количество миллисекунд с 1 января 1970 года, UTC). Но это не очень удобочитаемо для человека и требует дальнейшего преобразования для отображения в удобочитаемом формате.
Давайте обернем экземпляр Car , который мы использовали до сих пор, внутри класса Request со свойством datePurchased :
public class Request private Car car; private Date datePurchased; // standard getters setters >
Чтобы управлять строковым форматом даты и установить его, например, yyyy-MM-dd HH:mm az , рассмотрите следующий фрагмент:
ObjectMapper objectMapper = new ObjectMapper(); DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm a z"); objectMapper.setDateFormat(df); String carAsString = objectMapper.writeValueAsString(request); // output: ,"datePurchased":"2016-07-03 11:43 AM CEST">
Чтобы узнать больше о сериализации дат с Джексоном, прочитайте нашу более подробную статью .
4.4. Обработка коллекций
Еще одна небольшая, но полезная функция, доступная через класс DeserializationFeature , — это возможность генерировать нужный тип коллекции из ответа массива JSON.
Например, мы можем сгенерировать результат в виде массива:
String jsonCarArray = "[< \"color\" : \"Black\", \"type\" : \"BMW\" >, < \"color\" : \"Red\", \"type\" : \"FIAT\" >]"; ObjectMapper objectMapper = new ObjectMapper(); objectMapper.configure(DeserializationFeature.USE_JAVA_ARRAY_FOR_JSON_ARRAY, true); Car[] cars = objectMapper.readValue(jsonCarArray, Car[].class); // print cars
String jsonCarArray = "[< \"color\" : \"Black\", \"type\" : \"BMW\" >, < \"color\" : \"Red\", \"type\" : \"FIAT\" >]"; ObjectMapper objectMapper = new ObjectMapper(); ListCar> listCar = objectMapper.readValue(jsonCarArray, new TypeReferenceListCar>>()>); // print cars
Более подробная информация об обработке коллекций с помощью Jackson доступна здесь .
5. Вывод
Jackson — это надежная и зрелая библиотека сериализации/десериализации JSON для Java. API ObjectMapper предоставляет простой и гибкий способ анализа и создания объектов ответа JSON. В этой статье были рассмотрены основные особенности, которые делают библиотеку такой популярной.
Исходный код, прилагаемый к статье, можно найти на GitHub.
- 1. Обзор
- 2. Зависимости
- 3. Чтение и запись с помощью ObjectMapper
- 3.1. Объект Java в JSON
- 3.2. JSON в объект Java
- 3.3. JSON в Джексон JsonNode
- 3.4. Создание списка Java из строки массива JSON
- 3.5. Создание карты Java из строки JSON
- 4.1. Настройка функции сериализации или десериализации
- 4.2. Создание пользовательского сериализатора или десериализатора
- 4.3. Обработка форматов даты
- 4.4. Обработка коллекций