Как сериализовать HashMap как ArrayList как JSON?

1

У меня есть модель, у которой есть HashMap как вы видели ниже:

private Map<String, String>     attrMap     = new HashMap<String, String>();

и инициализировать его следующим образом:

attrMap.add("name", "value of name");
attrMap.add("content", "value of content");

но я хочу сериализовать это поле как ArrayList таких объектов:

[{name: "value of name"}, {content: "value of content"}]

ОБНОВЛЕНИЕ 1

Есть ли способ вызвать функцию во время сериализации следующим образом:

@JsonSerializer(serializeAttrMap)
private Map<String, String>     attrMap     = new HashMap<String, String>();

public String serializeAttrMap() {
    ArrayList<String> entries = new ArrayList<>(this.attrMap.size());
    for(Map.Entry<String,String> entry : attrMap.entrySet())
        entries.add(String.format("{%s: \"%s\"}",
            entry.getKey(), entry.getValue()));
    return Arrays.toString(entries.toArray());
}

ОБНОВЛЕНИЕ 2

Я использую этот класс для сериализации attrMap, но get can not start an object expecting field name ошибки can not start an object expecting field name.

import java.io.IOException;
import java.util.Map;

import org.codehaus.jackson.JsonGenerator;
import org.codehaus.jackson.JsonProcessingException;
import org.codehaus.jackson.map.JsonSerializer;
import org.codehaus.jackson.map.SerializerProvider;

public class AttrMapSerializer extends JsonSerializer<Map<String, String>> {

        @Override
        public void serialize(Map<String, String> attributes, JsonGenerator generator, SerializerProvider provider) throws IOException, JsonProcessingException {
            for (Map.Entry<String, String> attribute : attributes.entrySet())
            {
                generator.writeStartObject();
                generator.writeObjectField("name", attribute.getKey());
                generator.writeObjectField("content", attribute.getValue());
                generator.writeEndObject();
            }
        }
    }

Я начинаю Jackson

  • 0
    Поэтому создайте ArrayList, а затем сериализуйте его.
  • 0
    @RasoolGhafari - я обновил свой ответ, чтобы отразить ваше обновление. Обратите внимание, что нет способа работать с @JsonSerialize @JsonSerialize так, как вы запрашивали. Вам нужно предоставить класс, который наследует JsonSerializer .
Теги:
arraylist
jackson
hashmap

3 ответа

1

Следующая конструкция создаст желаемый результат:

@Test
public void testJackson() throws JsonProcessingException {
    // Declare the map
    Map<String, String> attrMap = new HashMap<>();

    // Put the data in the map
    attrMap.put("name", "value of name");
    attrMap.put("content", "value of content");

    // Use an object mapper
    final ObjectMapper objectMapper = new ObjectMapper();

    // Collect to a new object structure
    final List<ObjectNode> collected = attrMap.entrySet()
            .stream()
            .map(entry -> objectMapper.createObjectNode().put(entry.getKey(), entry.getValue()))
            .collect(Collectors.toList());

    // The output
    final String json = objectMapper.writeValueAsString(collected);

    System.out.println(json); // -> [{"name":"value of name"},{"content":"value of content"}]
}

Он использует комбинацию класса ObjectNode от Jackson вместе с некоторыми потоками Java 8 для сбора новых данных.

EDIT: после получения дополнительной информации от OP, где они попросили другой подход, я добавил эту альтернативу.

Другой подход - просто использовать @JacksonSerializer для атрибута.

// This is the serializer
public static class AttrMapSerializer extends JsonSerializer<Map<String, String>> {
    @Override
    public void serialize(
            final Map<String, String> value,
            final JsonGenerator jgen, final SerializerProvider provider) throws IOException {

        // Iterate the map entries and write them as fields
        for (Map.Entry<String, String> entry : value.entrySet()) {
            jgen.writeStartObject();
            jgen.writeObjectField(entry.getKey(), entry.getValue());
            jgen.writeEndObject();
        }
    }
}

// This could be the POJO
public static class PojoWithMap {
    private Map<String, String> attrMap = new HashMap<>();

    // This instructs the ObjectMapper to use the specified serializer
    @JsonSerialize(using = AttrMapSerializer.class)
    public Map<String, String> getAttributes() {
        return attrMap;
    }
}

public static void main(String... args) throws JsonProcessingException {
    final PojoWithMap pojoWithMap = new PojoWithMap();
    pojoWithMap.getAttributes().put("name", "value of name");
    pojoWithMap.getAttributes().put("content", "value of content");


    final String json = new ObjectMapper().writeValueAsString(pojoWithMap);
    System.out.println(json); // ->
}

Таким образом, сериализация вытесняется с помощью сериализатора и POJO не поврежден.

  • 0
    Я думаю, что вы получите тот же результат, непосредственно написав набор записей: objectMapper.writeValueAsString (attrMap.entrySet ())
  • 0
    @ArneBurmeister - это не совсем так. Если вы напечатаете его таким образом, вы получите ключ и значение для всех записей. Смотрите следующий пример: [{"key":"name","value":"value of name"},{"key":"content","value":"value of content"}] .
Показать ещё 2 комментария
0

Если вы не против делать это вручную, тогда возьмите следующий код (не тестировался, но должен работать):

ArrayList<String> entries = new ArrayList<>(attrMap.size());
for(Map.Entry<String,String> entry : attrMap.entrySet())
    entries.add(String.format("{%s: \"%s\"}",
            entry.getKey(), entry.getValue()));
return Arrays.toString(entries.toArray());

Это, вероятно, самый простой способ сделать это, поскольку, если вы хотите использовать библиотеку JSON, вам нужно либо изменить вывод (не рекомендуется, так как он накладывает плохую ремонтопригодность), либо написать собственный сериализатор/десериализатор для HashMap, который будет более сложным.

0

Попробуйте с помощью метода keySet и значений, который возвращает набор ключей и значений, а затем преобразует в arraylist что-то вроде:

List<String> keyList = new ArrayList<>(attrMap.keySet());
List<String> valueList = new ArrayList<>(attrMap.values());

Чтобы быть очень конкретным для вашего вопроса, вам нужно что-то вроде:

final Map<String, String>     attrMap     = new HashMap<String, String>();
attrMap.put("name", "value of name");
attrMap.put("content", "value of content");
List<String> keyList = new ArrayList<>(attrMap.size());
for (Map.Entry<String, String> entry : attrMap.entrySet()) {//iterate over map
  keyList.add("{" + entry.getKey() + ": \"" + entry.getValue() + "\"}");//add key followed by value
}
System.out.println(keyList);

Output:
[{name: "value of name"}, {content: "value of content"}]

Отметьте в стороне: в вашем посте кажется опечатка, так как на карте нет метода добавления. надеюсь, что вы имели в виду "положить" и "не добавлять". Также есть утилиты, такие как Gson, Jackson и т.д., Которые можно конвертировать в json-объект.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню