根据值的枚举类型从 HashMap 中删除条目

remove an entry from HashMap depending on the Enum type of the value

我需要从一个对象创建一个 json。 Object 包含一个 Name 类型的 List 成员变量。名称是一个 class,其中包含一个枚举名称类型。下面是 class:

public final class Person { private final List<Name> names; }

public class Name {

    private final String first;

    private final String last;

    private final String middle;

    private final NameType type;
}
public enum NameType {
    X,
    Y,
    Z
}

为 class Person 生成的 json 不应包含 NameType 为 Y 和 Z 的名称。下面是我尝试生成 json 的简单方法:

 Map<String, Object> personMap = mapper.readValue(person!=null ? mapper.writeValueAsString(person) : "{}", typeReference);

我需要从 personMap 中删除键“names”。我已经搜索了几种在序列化之前将其删除的方法,但这对我没有用。我遵循了本教程:https://www.baeldung.com/jackson-ignore-properties-on-serialization 并尝试使用类型和过滤器删除它,但因为这是一个枚举所以对我不起作用。所以,我有 2 个问题:

  1. 有没有办法不将名称 属性 作为基于 NameType 的序列化的一部分包含在内。
  2. 如果序列化完成后有什么方法可以删除。 下面是为地图生成的结构。

提前致谢!!

免责声明:我以前从未使用过Jackson,这是我第一次接触。我只是想在喝早茶的时候寻找一个小谜题来解决,这也能让我学到一些东西。所以我不确定是否有更好或更优雅的方法来做到这一点。

为了展示一个每个人都可以轻松编译和执行的 MCVE,这里是我的示例的更完整版本(包括 getter)类:

package de.scrum_master.Whosebug.q71358052;

public enum NameType {
  REAL,
  ARTIST,
  ONLINE
}
package de.scrum_master.Whosebug.q71358052;

public class Name {
  private final String first;
  private final String last;
  private final String middle;
  private final NameType type;

  public Name(String first, String last, String middle, NameType type) {
    this.first = first;
    this.last = last;
    this.middle = middle;
    this.type = type;
  }

  public String getFirst() {
    return first;
  }

  public String getLast() {
    return last;
  }

  public String getMiddle() {
    return middle;
  }

  public NameType getType() {
    return type;
  }
}
package de.scrum_master.Whosebug.q71358052;

import java.util.List;

public final class Person {
  private final List<Name> names;

  public Person(List<Name> names) {
    this.names = names;
  }

  public List<Name> getNames() {
    return names;
  }
}

this tutorial 中类似案例所述,我们可以将自定义 JsonSerializer<Name>BeanSerializerModifier 结合使用,将它们注册到 ObjectMapper 中的 SimpleModule:

package de.scrum_master.Whosebug.q71358052;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;

import java.io.IOException;

public class NameSerializer extends JsonSerializer<Name> {
  private final JsonSerializer<Object> defaultSerializer;

  public NameSerializer(JsonSerializer<Object> serializer) {
    defaultSerializer = serializer;
  }

  @Override
  public void serialize(Name value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
    if (value.getType() != NameType.REAL)
      return;
    defaultSerializer.serialize(value, gen, serializers);
  }

  @Override
  public boolean isEmpty(SerializerProvider provider, Name value) {
    return value == null || value.getType() != NameType.REAL;
  }
}
package de.scrum_master.Whosebug.q71358052;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.BeanDescription;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationConfig;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.BeanSerializerModifier;

import java.util.List;

public class JacksonDemo {
  public static void main(String[] args) throws JsonProcessingException {
    Person person = new Person(List.of(
      new Name("Edward", "Robinson", "G.", NameType.ARTIST),
      new Name("Emanuel", "Goldenberg", null, NameType.REAL),
      new Name("Эмануэль", "Голденберг", null, NameType.REAL),
      new Name("Eddie", "The Gangster", null, NameType.ONLINE)
    ));

    ObjectMapper objectMapper = getObjectMapper();
    String personJson = objectMapper.writeValueAsString(person);

    System.out.println(personJson.contains("ARTIST"));      // false
    System.out.println(personJson.contains("ONLINE"));      // false
    System.out.println(personJson.contains("Goldenberg"));  // true
    System.out.println(personJson.contains("Голденберг"));  // true
    System.out.println(personJson);
  }

  private static ObjectMapper getObjectMapper() {
    ObjectMapper objectMapper = new ObjectMapper();
    objectMapper.setSerializationInclusion(JsonInclude.Include.NON_EMPTY);
    objectMapper.registerModule(
      new SimpleModule() {
        @Override
        public void setupModule(SetupContext context) {
          super.setupModule(context);
          context.addBeanSerializerModifier(
            new BeanSerializerModifier() {
              @Override
              public JsonSerializer<?> modifySerializer(SerializationConfig config, BeanDescription beanDesc, JsonSerializer<?> serializer) {
                if (Name.class.isAssignableFrom(beanDesc.getBeanClass()))
                  return new NameSerializer((JsonSerializer<Object>) serializer);
                return serializer;
              }
            }
          );
        }
      }
    );
    return objectMapper;
  }
}

控制台日志应该是:

false
false
true
true
{"names":[{"first":"Emanuel","last":"Goldenberg","type":"REAL"},{"first":"Эмануэль","last":"Голденберг","type":"REAL"}]}

哦,顺便说一句,以防万一不是每个人都知道 Edward G. Robinson 是谁...