【问题标题】:Override toString of internal object覆盖内部对象的 toString
【发布时间】:2019-01-03 11:52:00
【问题描述】:

我已经重写了一个名为 Skeleton 的对象的 toString(),所以当我调用 toString() 时,颜色变量被排除在外。

public class Skeleton
{
    private List bones;
    private Color color;

    //  getters & setters

    @Override
    public String toString() 
    {
        String s = null;

        ObjectMapper mapper = new ObjectMapper();
        mapper.setAnnotationIntrospector(new JacksonAnnotationIntrospector(){
        @Override
        public boolean hasIgnoreMarker(final AnnotatedMember m) {
                List<String> exclusions = Arrays.asList("color");
                return exclusions.contains(m.getName())|| super.hasIgnoreMarker(m);
            }
        });

        try 
        {
            s = mapper.writeValueAsString(this);

        } catch (JsonProcessingException e) {

            e.printStackTrace();
        }

        return s;
    }
}

但是,当我将 Skeleton 对象作为变量添加到名为 Body 的对象并在 Body 上调用 toString() 时,color 字段包括骷髅。

public class Body
{
    private Skeleton skeleton = ....

有谁知道如何让 Body 使用 Skeleton 中重写的 toString() 方法?

【问题讨论】:

  • ...覆盖toString() in Body?
  • 问题当然是在 Body.toString 中(可能)使用 ObjectMapper 绕过 Skeleton.toString。由于 ObjectMapper 也很昂贵,所以它的使用是有问题的。最小的变化是将toString 替换为represent(ObjectMapper, StringWriter) 或类似的接口,以使用一个对象映射器遍历整个对象层次结构。
  • 看到这个,baeldung.com/jackson-ignore-properties-on-serialization,检查部分5. Ignore Fields Using Filters

标签: java jackson tostring objectmapper jackson-databind


【解决方案1】:

您可以使用 Jackson @987654321,而不是手动排除 toString 方法中的字段,如果需要排除其他字段(或者如果不应再排除 color),这可能会很乏味且容易出错@注解。然后可以覆盖Skeleton中的toString方法打印序列化字符串:

public class Skeleton {

    private List bones;

    @JsonIgnore
    private Color color;

    @Override
    public String toString() {

        try {
            ObjectMapper mapper = new ObjectMapper();
            return mapper.writeValueAsString(this);
        } 
        catch (JsonProcessingException e) {
            e.printStackTrace();
        }
    }
}

如 cmets 中所述,如果经常使用 SkeletontoString 方法,则使用 ObjectMapper 将对象序列化为 String 可能会很昂贵。如果性能成为问题,ObjectMapper 应该只用于序列化最顶层的对象(即Body),而不是在每个中间对象(即Skeleton):

public class Skeleton {

    private List bones;

    @JsonIgnore
    private Color color;

    // Getters & setters
}

public class Body {

    private Skeleton skeleton;

    @Override
    public String toString() {

        try {
            ObjectMapper mapper = new ObjectMapper();
            return mapper.writeValueAsString(this);
        } 
        catch (JsonProcessingException e) {
            e.printStackTrace();
        }
    }
}

根据 OP 的反馈进行编辑

如果您只想忽略特定ObjectMapper 的字段,您可以创建SimpleBeanPropertyFilter 并指定要忽略的字段名称:

public class Skeleton {

    private List bones;
    private Color color;

    @Override
    public String toString() {

        try {
            ObjectMapper mapper = new ObjectMapper();
            FilterProvider filters = new SimpleFilterProvider()
                .addFilter("ignoreColor", SimpleBeanPropertyFilter.serializeAllExcept("color"));
            return mapper.writer(filters).writeValueAsString(this);
        } 
        catch (JsonProcessingException e) {
            e.printStackTrace();
        }
    }
}

有关详细信息,请参阅Jackson Ignore Properties on Marshalling 上的第 5 节:使用过滤器忽略字段

【讨论】:

  • 不幸的是,上述方法的效果有点太好了。如果我使用 @JsonIgnore 注释,当我将 Java 对象转换为 JSON 对象并通过网络发送它时,关联的字段将被完全删除。我需要保留该字段,但当我在 Java 对象上调用 toString() 时将其排除,手动排除似乎允许这样做。您是否知道如何手动排除内部对象的字段?
  • @T-Pane 现在我明白了。我误解了你原来的问题。我已经更新了上面的答案,以包含一个处理您的评论的部分。
【解决方案2】:

您必须重写 Body 类的 toString() 方法并包含您认为必要的任何细节。包括实例变量private Skeleton skeleton = ...toString() 方法以及您在Body 类中可能拥有的所有其他成员变量。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-13
    • 2012-10-13
    • 1970-01-01
    相关资源
    最近更新 更多