2014-12-27 2 views
1

У меня есть модель, которые имеют HashMap, как вы видели ниже:Как сериализовать HashMap как ArrayList как JSON?

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()); 
} 

UPDATE 2

Я использую этот класс для сериализации attrMap, но получить 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' именно так, как вы просили. Вам нужно предоставить класс, который наследует 'JsonSerializer'. – wassgren

ответ

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-объект.

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: После получения дополнительной информации от ОП, где они запросили другой подход, я добавил эту альтернативу.

Другой подход - просто использовать атрибут @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 content "}]'. – wassgren

+0

Правильно, слишком быстро, но правильно поставил голос! –

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, который будет более сложным.

Смежные вопросы