在JSON上应用掩码以仅保留必需数据 [英] Apply a mask on a JSON to keep only mandatory data

查看:56
本文介绍了在JSON上应用掩码以仅保留必需数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个API,该API会使用一些潜在的必需数据来创建临时会话:

I have an API which takes some potentially mandatory data to create a temporary session:

例如:首先,我的 POST/signup 终结点用户需要向我发送以下数据:

e.g.: at first, my POST /signup endpoint user need to send me the following data:

{
  "customer": {
    "age": 21,
    "ssn": "000 00 0000",
    "address": {
      "street": "Customer St.",
      "phone": "+66 444 333 222"
    }
  }
}

我们称之为 JSON a .

另一方面,我有一些法律伙伴需要一些这些数据,但不是全部:

On the other hand, I have some legal partners which requires some of these data, but not all of them:

例如:

{
  "customer": {
    "ssn": "The SSN is mandatory to register against XXX Company",
    "address": {
      "phone": "XXX Company will send a text message to validate your registration"
    }
  }
}

我们称之为 JSON b .

由于最近的法律限制,在我的信息系统中,我只能保留 强制性数据,以供用户随身携带他选择的工作流程.

Due to recent legal restrictions, in my information system, I have to keep only mandatory data for the user to carry with his chosen workflow.

我的问题:是否有一个函数(可以内置在Jackson或其他JSON处理库中,或者您建议使用的算法),我可以应用给定的 JSON b JSON a ,它将输出以下JSON:

Hence my question: is there a function (either built in Jackson or some other JSON handling library or an algorithm you would recommend) I could apply such that given JSON b and JSON a, it would output the following JSON:

{
  "customer": {
    "ssn": "000 00 0000",
    "address": {
      "phone": "+66 444 333 222"
    }
  }
}


想一想,我发现了一些可能是解决方案的方法:


Thinking a bit, I found something which might be a solution:

  • JSON a JSON b 合并,冲突时采用 JSON b 值,将结果命名为 JSON c
  • JSON c JSON a 之间进行区分(丢弃等于数据),在发生冲突时采用 JSON a
  • merge JSON a with JSON b, on conflict take JSON b values, name the result JSON c
  • make a diff (drop equals data) between JSON c and JSON a, on conflict take JSON a values

我知道可以使用 com.fasterxml.jackson.databind.ObjectMapper#readerForUpdating 完成使用Jackson合并两个JSON,因此我的问题可以简化为:有没有一种方法可以使两种JSON之间的区别,并提供解决冲突的功能?

I know merging two JSON using Jackson can be done using com.fasterxml.jackson.databind.ObjectMapper#readerForUpdating, so my question could be reduced to: is there a way to make a diff between two JSON and give a conflict resolution function?

推荐答案

我建议使用基于令牌/事件/流的解决方案.以下只是使用小型解析器/生成器lib的说明 https://github.com/anatolygudkov/green-果冻(Gson和Jackson都提供了面向流的API):

I'd suggest to use token/event/stream-based solution. The following is just an illustration using tiny parser/generator lib https://github.com/anatolygudkov/green-jelly (both Gson and Jackson also provide stream-oriented API):

import org.green.jelly.AppendableWriter;
import org.green.jelly.JsonEventPump;
import org.green.jelly.JsonNumber;
import org.green.jelly.JsonParser;

import java.io.StringWriter;
import java.io.Writer;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;

public class FilterMyJson {

    private static final String jsonToFilter = "{\n" +
            "  \"customer\": {\n" +
            "    \"age\": 21,\n" +
            "    \"ssn\": \"000 00 0000\",\n" +
            "    \"address\": {\n" +
            "      \"street\": \"Customer St.\",\n" +
            "      \"phone\": \"+66 444 333 222\"\n" +
            "    }\n" +
            "  }\n" +
            "}";

    public static void main(String[] args) {
        final StringWriter result = new StringWriter();

        final JsonParser parser = new JsonParser();
        parser.setListener(new MyJsonFilter(result, "age", "street"));
        parser.parse(jsonToFilter); // if you read a file with a buffer,
        // call parse() several times part by part in a loop until EOF
        parser.eoj(); // and then call .eoj()

        System.out.println(result);
    }

    static class MyJsonFilter extends JsonEventPump {
        private final Set<String> objectMembersToFilter;
        private boolean currentObjectMemberIsAllowed;

        MyJsonFilter(final Writer output, final String... objectMembersToFilter) {
            super(new AppendableWriter<>(output));
            this.objectMembersToFilter = new HashSet<>(Arrays.asList(objectMembersToFilter));
        }

        @Override
        public boolean onObjectMember(final CharSequence name) {
            currentObjectMemberIsAllowed =
                    !objectMembersToFilter.contains(name.toString());
            return super.onObjectMember(name);
        }

        @Override
        public boolean onStringValue(final CharSequence data) {
            if (!currentObjectMemberIsAllowed) {
                return true;
            }
            return super.onStringValue(data);
        }

        @Override
        public boolean onNumberValue(final JsonNumber number) {
            if (!currentObjectMemberIsAllowed) {
                return true;
            }
            return super.onNumberValue(number);
        }
    }
}

打印:

{
 "customer":
 {
  "ssn": "000 00 0000",
  "address":
  {
   "phone": "+66 444 333 222"
  }
 }
}

代码相当简化.目前,它仅过滤掉字符串和数字标量.不支持对象层次结构.因此,在某些情况下,您可能需要改进代码.

The code is quite simplified. For now it filters out only string and number scalars. No object hierarchy is supported. You may need to improve the code for some cases therefore.

此类解决方案的道具:

  • 文件/数据不需要完全加载到内存中,您可以毫无问题地处理兆位/演出
  • 它的工作速度要快得多,特别是对于大文件
  • 使用此模式很容易实现任何自定义类型/转换规则.例如,对过滤器进行参数化很容易,不必在每次更改数据结构时都重新编译代码

这篇关于在JSON上应用掩码以仅保留必需数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆