我有一个JSON字符串,我使用Gson转换为JSON Object。但是,我想使用containsKey
作为不区分大小写的方式。
这就是我现在正在做的事情。
ByteBuffer buffer = ByteBuffer.wrap(payload);
String data = forName("UTF-8").newDecoder().decode(buffer).toString();
Gson gson = new Gson();
Map<String, String> map = gson.fromJson(data, new TypeToken<HashMap<String, Object>>() {
}.getType());
然后我使用此方法isTupleValid
来检查元组是否有效。
private boolean isTupleValid(Map<String, String> map) {
return map != null && map.containsKey(TYPE)
&& map.containsKey(XID)
&& map.containsKey(CTP)
&& map.get(TYPE).equals("pageview");
}
但是,有时json字符串可能是
{"xid": "xid"}
或它可以是{"xID":"xid"}
有没有办法以区分大小写的方式使用containsKey
?
答案 0 :(得分:0)
gson.fromJson(data, new TreeMap<>(...).getClass())
没有多大意义,因为getClass()
只返回对象类,而不是它的内部状态 - 简单来说,无论传递给{的参数是什么,总是得到TreeMap.class
{1}}构造函数。
对我来说,有两种选择。他们两个使用“规范化”地图,各有利弊。
首先,让我们创建公共类,以便在两种方法演示之间分享基础知识:
TreeMap
此选项不会触及原始的反序列化策略,因此使用代码必须检查不区分大小写的本身。有必要将“地图规范化”代码放在有意义的地方。请注意,原始地图保持不变。
final class Commons {
private Commons() {
}
static final String CTP = "ctp";
static final String TYPE = "type";
static final String XID = "xid";
static final String JSON_1 = "{\"xid\":\"foo\",\"type\":\"pageview\",\"ctp\":\"ctp\"}";
static final String JSON_2 = "{\"xID\":\"foo\",\"tYPE\":\"pageview\",\"cTP\":\"ctp\"}";
static Map<String, Object> normalizeMap(final Map<String, Object> map) {
final Map<String, Object> normalized = new TreeMap<>(CASE_INSENSITIVE_ORDER);
normalized.putAll(map);
return normalized;
}
}
此选项创建一个特殊的GSON实例,以“规范化”方式反序列化public final class CaseInsensitive1 {
private CaseInsensitive1() {
}
public static void main(final String... args) {
final Gson gson = new Gson();
@SuppressWarnings("unchecked")
final Map<String, Object> map1 = gson.fromJson(JSON_1, Map.class);
@SuppressWarnings("unchecked")
final Map<String, Object> map2 = gson.fromJson(JSON_2, Map.class);
out.println(isTupleValid(map1));
out.println(isTupleValid(map2));
}
private static boolean isTupleValid(final Map<String, Object> map) {
if ( map == null ) {
return false;
}
final Map<String, Object> ciMap = normalizeMap(map);
return ciMap.containsKey(TYPE)
&& ciMap.containsKey(XID)
&& ciMap.containsKey(CTP)
&& ciMap.get(TYPE).equals("pageview");
}
}
。请注意,自从我为该具体类型映射反序列化策略后,Map<String, Object>
随处可见。当然,它可能只映射到mapStringObjectType
。 Map.class
需要另一个GSON实例才能“继承”您可能需要的基本构建的行为。尽管decorateGson
方法现在与您的方法等效,但此选项的缺点是您丢失了原始JSON对象的属性顺序。但是,您可能希望使用case-insensitive maps not based on TreeMap(不确定,但它可以使地图以不区分大小写的方式保持原始属性顺序)。
isTupleValid
对我来说,选项#1看起来更好,因为它没有以任何方式装饰原始反序列化的对象(如果我以后需要它在代码中区分大小写?)并且执行不区分大小写的检查只有才真正需要。
答案 1 :(得分:0)
如果只需要检查键是否存在而无需检索值。您可以访问keySet
。流式传输并使用anyMatch
谓词调用ignoreCase
。就您而言:
return ciMap.keySet().stream().anyMatch(key -> key.equalsIgnoreCase(TYPE))
&& ciMap.keySet().stream().anyMatch(key -> key.equalsIgnoreCase(XID))
&& ciMap.keySet().stream().anyMatch(key -> key.equalsIgnoreCase(CTP))
&& ciMap.get(TYPE).equals("pageview");
PS:您可以考虑使用适当的数据结构。在这种情况下,键不能相等,但是返回true。这违反了地图合同。