Есть ли в org.kohsuke.github встроенный механизм для сериализации объектов GHRepository в JSON?

Я использую Java Github API из org.kohsuke.github, чтобы получить объект GHRepository. Я хочу сериализовать этот объект в JSON. Есть ли способ сделать это в org.kohsuke.github клиенте? Возможно, используется Jackson?

В настоящее время при использовании jackson мне пришлось создать пользовательское pojo, чтобы избежать встречи Jackson с нулевыми ключами и значениями Map. Я подозреваю, что в этой библиотеке github уже есть код для этого, так как я вижу, как он сериализуется в JSON в GitHub.java, но я не вижу общедоступных средств использования этого. Приведенный ниже код выполняет итерацию по всем моим репозиториям во всех моих организациях, чтобы получить JSON-представление репо, которое затем будет сохранено в базе данных.

// Iterate over all orgs that I can see on enterprise
github.listOrganizations().withPageSize(100).forEach( org -> {

    // Get all the repositories in an org
    Map<String, GHRepository> ghRepositoryMap = org.getRepositories();

    // Iterate over each repo object and serialize
    for (Map.Entry<String, GHRepository> entry :ghRepositoryMap.entrySet()  ) {

        // Serialize to JSON
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); //Handles null fields ok
        String jsonStr = objectMapper.writeValueAsString(entry.getValue()); // <-- this fails due to null key

    }
}

Последняя строка приводит к следующему:

com.fasterxml.jackson.databind.JsonMappingException: нулевой ключ для карты не разрешен в JSON (использовать преобразователь NullKeySerializer?) (через цепочку ссылок: org.kohsuke.github.GHRepository ["responseHeaderFields"] -> java.util.Collections $ UnmodifiableMap ["ноль"])

При осмотре я считаю, что это не единственный null ключ. Я, вероятно, мог бы настроить это чертовски хорошо, добавив миксины для их обработки, но я ищу встроенный способ в org.kohsuke.github библиотеке, который упрощает это, поскольку он, похоже, способен делать это внутренне.


person Damon    schedule 10.09.2019    source источник


Ответы (1)


Вы должны реализовать и зарегистрировать NullKeySerializer. См. Пример ниже:

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.SerializerProvider;

import java.io.IOException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class JsonApp {

    public static void main(String[] args) throws Exception {
        Map<String, List<String>> map = new HashMap<>();
        map.put(null, Arrays.asList("A", "B", "C"));
        map.put("regular-key", Arrays.asList("X", "Y"));

        ObjectMapper mapper = new ObjectMapper();
        mapper.enable(SerializationFeature.INDENT_OUTPUT);
        mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
        mapper.getSerializerProvider().setNullKeySerializer(new NullKeySerializer());

        System.out.println(mapper.writeValueAsString(map));
    }
}

class NullKeySerializer extends JsonSerializer<Object> {
    @Override
    public void serialize(Object value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
        gen.writeFieldName("null");
    }
}

Над кодом печатается:

{
  "null" : [ "A", "B", "C" ],
  "regular-key" : [ "X", "Y" ]
}

Кроме того, не следует создавать ObjectMapper экземпляра для каждой записи. Вы можете создать его один раз и использовать для всех элементов.

person Michał Ziober    schedule 10.09.2019
comment
Спасибо! Это работает! Также благодарю за то, что я каждый раз создавал новый ObjectMapper. - person Damon; 11.09.2019