【问题标题】:Jackson Change JsonIgnore DynamicallyJackson 动态更改 JsonIgnore
【发布时间】:2012-01-01 01:45:36
【问题描述】:

我有一个类,里面也有变量。有时我想忽略一些字段,有时在反序列化时不想忽略(也许也在序列化时)。我如何在杰克逊做到这一点?

【问题讨论】:

    标签: java json deserialization jackson


    【解决方案1】:

    对于序列化,“filtering properties”博客条目应该会有所帮助。反序列化方面的支持较少,因为更常见的是要过滤掉写入的内容。

    一种可能的方法是对JacksonAnnotationIntrospector 进行子类化,覆盖自省方法(和/或字段)的可忽略性以使用您想要的任何逻辑的方法。

    如果您提供一个实际应用示例,也可能会有所帮助,即您试图防止反序列化的内容和原因。

    【讨论】:

    • 这里是一个解释:jroller.com/RickHigh/entry/filtering_json_feeds_from_spring我不使用 Roo 和 aspectj 代码在我的 Intellij IDEA8 上给出错误(无法识别 thisJoinPoint 和继续方法)。如果我能像描述的那样将它实现为注释,那就太好了。
    • 我有一个 Spring 3 REST 应用程序。我在服务器端有一个 bean,我在客户端列出了它们。但是它有很多字段,我没有在表中列出我的 bean 的每个字段。然而,在另一个页面上,我在另一个表中列出了我的 bean 的所有字段。所以我的目的是我不想将所有信息发送到客户端以提高效率。
    • 好的:但是要明确一点——发送东西的时候,你通常在谈论序列化;反序列化是相反的(将 JSON 读入对象)。那么也许您正在寻找序列化功能?如果是这样,我提到的链接会非常有用吗?
    • 序列化对我来说非常重要,你是对的。我阅读了该链接,我将尝试实现它,感谢您的帮助。
    • 链接太棒了!我发现完全动态过滤:@JsonFilter 非常适合我的用例,我希望在获取(序列化)方面进行更多控制,但不能超出某个级别,因为它最终会被递归获取。 ORM 往往是这样的。
    【解决方案2】:

    您可能想要使用 JsonViews(最初来自 http://wiki.fasterxml.com/JacksonJsonViews - 现在已损坏 - 网络存档链接:https://web.archive.org/web/20170831135842/http://wiki.fasterxml.com/JacksonJsonViews)

    引用它:

    首先,定义视图意味着声明类;您可以重用现有的,或者只是创建虚假类——它们只是带有关系信息的视图标识符(子继承父视图成员身份):

     // View definitions:
      class Views {
                static class Public { }
                static class ExtendedPublic extends PublicView { }
                static class Internal extends ExtendedPublicView { }
      }
    
      public class Bean {
                // Name is public
                @JsonView(Views.Public.class) String name;
                // Address semi-public
                @JsonView(Views.ExtendPublic.class) Address address;
                // SSN only for internal usage
                @JsonView(Views.Internal.class) SocialSecNumber ssn;
      }
    

    有了这样的视图定义,序列化可以这样完成:

     // short-cut:
      objectMapper.writeValueUsingView(out, beanInstance, ViewsPublic.class);
    
      // or fully exploded:
      objectMapper.getSerializationConfig().setSerializationView(Views.Public.class);
      // (note: can also pre-construct config object with 'mapper.copySerializationConfig'; reuse)
      objectMapper.writeValue(out, beanInstance); // will use active view set via Config
    
      // or, starting with 1.5, more convenient (ObjectWriter is reusable too)
      objectMapper.viewWriter(ViewsPublic.class).writeValue(out, beanInstance);
    and result would only contain 'name', not 'address' or 'ssn'.
    

    【讨论】:

      【解决方案3】:

      你应该看看最近 Jackson 版本的modules feature。

      一种可能的机制是使用BeanDeserializerModifier。

      我一直在寻找有用的在线教程或示例,但没有立即出现。如果对您的上下文有更多了解,则可能会有所作为。您是手动管理ObjectMappers,还是在 JAX-RS 设置中使用它们,在 Spring 中注入,还是什么?

      【讨论】:

        【解决方案4】:

        我搜索了整个网络(是的,我这样做了)以找到答案。然后我自己写了一些东西。

        我正在使用 Jackson 离子反序列化。我编写了一个自定义阅读器,它会动态忽略这些字段。

        你可以对 json 反序列化做同样的事情。

        让我们假设一个这样的实体。

        User {
            id
            name
            address {
               city
            }
        }
        

        创建一个树结构来表示字段选择。

        public class IonField {
        
            private final String name;
            private final IonField parent;
            private final Set<IonField> fields = new HashSet<>();
        
            // add constructs and stuff
        }
        

        从 amazon ion-java https://github.com/amzn/ion-java 扩展的自定义离子读取器

        public class IonReaderBinaryUserXSelective extends IonReaderBinaryUserX {
        
            private IonField _current;
            private int hierarchy = 0;
        
            public IonReaderBinaryUserXSelective(byte[] data, int offset, int length,
                                                 IonSystem system, IonField _current) {
                super(system, system.getCatalog(), UnifiedInputStreamX.makeStream(data, offset, length));
                this._current = _current;
            }
        
            @Override
            public IonType next() {
                IonType type = super.next();
        
                if (type == null) {
                    return null;
                }
        
                String file_name = getFieldName();
        
                if (file_name == null || SystemSymbols.SYMBOLS.equals(file_name)) {
                    return type;
                }
        
                if (type == IonType.STRUCT || type == IonType.LIST) {
                    IonField field = _current.getField(getFieldName());
                    if (field != null) {
                        this._current = field;
                        return type;
                    } else {
                        super.stepIn();
                        super.stepOut();
                    }
                    return next();
                } else {
                    if (this._current.contains(file_name)) {
                        return type;
                    } else {
                        return next();
                    }
                }
            }
        
            @Override
            public void stepIn() {
                hierarchy = (hierarchy << 1);
                if (getFieldName() != null && !SystemSymbols.SYMBOLS.equals(getFieldName())) {
                    hierarchy = hierarchy + 1;
                }
                super.stepIn();
            }
        
            @Override
            public void stepOut() {
                if ((hierarchy & 1) == 1) {
                    this._current = this._current.getParent();
                }
                hierarchy = hierarchy >> 1;
                super.stepOut();
            }
        
        

        构建动态视图。这棵树动态创建并传递给阅读器进行反序列化。

        假设我们只需要地址中的城市。

        IonField root = new IonField("user", null);
        
        IonField address = new IonField("address", root);
        IonField city = new IonField("city", address);
        address.addChild(city);
        
        root.addChild(id);
        
        
        //now usual stuff.
        
        IonFactory ionFactory = new IonFactory();
        IonObjectMapper mapper = new IonObjectMapper(ionFactory);
        
        File file = new File("file.bin"); // ion bytes
        
        byte[] ionData =  Files.readAllBytes(file.toPath());
        
        IonSystem ionSystem = IonSystemBuilder.standard().build();
        IonReader ionReader = new IonReaderBinaryUserXSelective(ionData, 0, ionData.length, ionSystem, root);
        
        User user = mapper.readValue(ionReader, User.class);
        
        

        【讨论】:

        猜你喜欢
        • 2018-10-13
        • 1970-01-01
        • 1970-01-01
        • 2018-12-31
        • 2019-09-14
        • 1970-01-01
        • 1970-01-01
        • 2018-11-18
        • 1970-01-01
        相关资源
        最近更新 更多