簡體   English   中英

如何將 java.util.Optional 與 REST API 一起使用?

[英]How to use java.util.Optional with REST API?

我有一個看起來像的課程

public class ActiveDirectorySetup implements Serializable {
  private ActiveDirectoryDataSource activeDirectoryDataSource;
  private Optional<ShActiveDirectorySettings> shActiveDirectorySettings;
  private Optional<SaActiveDirectorySettings> saActiveDirectorySettings;
 // ...
}

我通過 API 將其發送為

      Optional<ActiveDirectoryConfiguration> configuration = store.getConfiguration();
      if (configuration.isPresent()) {
        return configuration.get();
      }

我在瀏覽器上看到的是

[
   {
      "activeDirectoryDataSource":{
         "host":"localhost",
         "port":0,
         "userName":"user",
         "password":"password",
         "activeDirectoryQueryConfig":{
            "base":{
               "present":false
            },
            "filter":"filter",
            "attributes":[

            ]
         },
         "activeDirectorySslSettings":{
            "present":false
         }
      },
      "shActiveDirectorySettings":{
         "present":true
      },
      "saActiveDirectorySettings":{
         "present":true
      }
   }
]

對於看起來像的有效載荷

{
    "activeDirectorySetups": [
        {
            "activeDirectoryDataSource": {
                "host": "localhost",
                "port": 0,
                "userName": "user",
                "password": "password",
                "activeDirectoryQueryConfig": {
                    "base": null,
                    "filter": "filter",
                    "attributes": []
                },
                "activeDirectorySslSettings": null
            },
            "shActiveDirectorySettings": {
                "enableUserMapping": true,
                "attributes": null
            },
            "saActiveDirectorySettings": null
        }
    ]
}

如您所見,我得到的是{"present":true}而不是實際值。

我正在使用jackson-datatype-jdk8來完成這項工作。 如何強制它用實際值替換{"present":true} - null{"enableUserMapping": true, "attributes": null}

我很確定您需要為此編寫自定義序列化/反序列化功能。

解串器

public class OptionalDeserializer<T> extends StdDeserializer<Optional<T>> {

    private ObjectMapper customObjectMapper;

    private Class<T> type;

    /**
     * @param customObjectMapper any ObjectMapper, possibly with deserialization logic for the wrapped type
     * @param type the wrapped type
     */
    public OptionalDeserializer(ObjectMapper customObjectMapper, Class<T> type) {
        this(Optional.class);
        this.customObjectMapper = customObjectMapper;
        this.type = type;
    }

    // At least one type-based constructor is required by Jackson
    private OptionalDeserializer(Class<?> vc) {
        super(vc);
    }

    @Override
    public Optional<T> deserialize(JsonParser jsonParser, DeserializationContext ctx) throws IOException {
        // Read entire tree
        JsonNode treeNode = jsonParser.getCodec().readTree(jsonParser);

        // Check if "present" is true
        if (treeNode.has("present") && treeNode.get("present").asBoolean()) {
            // Read your wrapped value
            return Optional.of(customObjectMapper.treeToValue(treeNode.get("data"), type));
        }

        // Return empty() by default
        return Optional.empty();
    }
}

序列化器

請注意,您可以在管道中的任何位置為Box類型包含自定義ObjectMapper 為簡單起見,在序列化程序中省略了它。

public class OptionalSerializer<T> extends StdSerializer<Optional<T>> {

    public OptionalSerializer(Class<T> type) {
        this(TypeFactory.defaultInstance().constructParametricType(Optional.class, type));
    }

    protected OptionalSerializer(JavaType javaType) {
        super(javaType);
    }

    @Override
    public void serialize(Optional<T> value, JsonGenerator gen, SerializerProvider provider) throws IOException {
        gen.writeStartObject();
        if (value.isPresent()) {
            gen.writeBooleanField("present", true);
            gen.writeObjectField("data", value.get());
        } else {
            gen.writeBooleanField("present", false);
        }
        gen.writeEndObject();
    }
}

用法示例:

public static void main(String[] args) throws IOException {
    ObjectMapper optionalMapper = new ObjectMapper();

    SimpleModule module = new SimpleModule();
    // Add any custom deserialization logic for Box objects to this mapper
    ObjectMapper boxMapper = new ObjectMapper();
    OptionalDeserializer<Box> boxOptionalDeserializer = new OptionalDeserializer<>(boxMapper, Box.class);
    OptionalSerializer<Box> boxOptionalSerializer = new OptionalSerializer<>(Box.class);
    module.addDeserializer(Optional.class, boxOptionalDeserializer);
    // use addSerializer(JsonSerializer<?> ser), not addSerializer(Class<? extends T> type, JsonSerializer<T> ser)
    // The generic types involved here will otherwise not let the program compile
    module.addSerializer(boxOptionalSerializer);
    optionalMapper.registerModule(module);

    String json = "{\"present\": true, \"data\": {\"myValue\": 123}}";
    Optional optional = optionalMapper.readValue(json, Optional.class);

    @SuppressWarnings("unchecked") // Guaranteed safe cast
    Optional<Box> boxOptional = (Optional<Box>) optional;

    // Prints "123"
    boxOptional.ifPresent(box -> System.out.println(box.getMyValue()));

    // Prints the contents of "json" (variable defined above)
    System.out.println(optionalMapper.writeValueAsString(boxOptional));
}

其中Box只是一個簡單的示例類:

private static class Box {
    private int myValue;

    public int getMyValue() {
        return myValue;
    }

    public void setMyValue(int myValue) {
        this.myValue = myValue;
    }
}

我認為您在 Java 8 中使用 Optional 時依賴於默認的 Java 序列化。請注意 Optional 不可序列化,因此,您必須編寫自己的 JSON 序列化器/反序列化器。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM