我有一个 json 部分,其中包含以下内容:
{"tokenType":"电子邮件","tokenList":["token1","token2","token3","token4"]}
我有一个 flink 作业正在记录从 kafka 接收的有效负载,我需要在日志中屏蔽这些令牌值(电子邮件/电话号码)。为此,我们使用一个实用程序,它将屏蔽所有捕获组的前 x 个字符(从索引 1 开始)。
我的问题是,当列表长度可变时,我找不到可以捕获所有这些标记的正则表达式。
我可以编写可以捕获整个列表的正则表达式,但问题是整个匹配将被视为捕获组,并且前 x 个字符将被屏蔽。
我希望我的日志看起来像这样,对于 x = 3:
{"tokenType":"电子邮件","tokenList":["***en1","***en2","***en3","***en4"]}
我需要我的正则表达式来捕获这些标记的值。
flatMap()
函数来完成此操作,以支持从单个元素创建多个元素。由于您的有效负载已经接受基于 JSON 的字符串,因此您可以将其解析为结构化 JSON 对象,然后提取所需的元素并将其发送到下游。
类似:
// Function to take in a single JSON string and output multiple string elements
class TokenMaskingFunction: FlatMapFunction<String, String>{
override fun flatMap(input: String, collector: Collector<String>) {
try {
// Construct your JSON node
val structuredJson: JsonNode = mapper.readTree(input)
// Capture your tokens
val tokens: JsonNode = structuredJson.get("tokenList")
if (tokens.isArray) {
for (token in tokens) {
// Extract and mask your token before sending downstream
val maskedToken = maskFunction(token.toString())
collector.collect(maskedToken)
}
}
} catch (e: Exception) {
// Handle accordingly / log / ignore
}
}
private fun mask(token: String): String {
// Do your masking here
}
companion object {
// Define some static JSON parser here (static is important)
val mapper = ObjectMapper()
}
}
然后您只需在从 JSON 字符串源映射后使用它即可:
streamEnv
.fromSource(yourJsonStringSource)
.flatMap(TokenMaskingFunction())
.process(...)
我使用 Pattern 类做了一个粗略的解决方案。它不是很有效,但适用于给定的示例。
public static void main(String[] args) {
String val = " {\"tokenType\":\"email\",\"tokenList\":[\"token1\",\"token2\",\"token3\",\"token4\"]}";
Pattern p = Pattern.compile("(?:\\G(?!^)|\"tokenList\":\\[)\"(?<elem>[^\"]*)\",?");
Matcher m = p.matcher(val);
int n = 3;
StringBuilder builder = new StringBuilder();
while (m.find()) {
String elem = m.group("elem");
if (elem != null) {
m.appendReplacement(builder, m.group().replace(elem, "*".repeat(n).concat(elem.substring(n))));
}
}
m.appendTail(builder);
System.out.println(builder);
}