Java JSON查询过滤器传输
我想以JSON的形式从客户机传输到服务器WHERE子句。 我已在服务器上创建了Java JSON查询过滤器传输,java,json,generics,gson,Java,Json,Generics,Gson,我想以JSON的形式从客户机传输到服务器WHERE子句。 我已在服务器上创建了FilterInfo.class和Filter.class: public class Filter<T> { private String fieldName; private String operand; private T value; } public class FilterInfo { private List<Filt
FilterInfo.class
和Filter.class
:
public class Filter<T> {
private String fieldName;
private String operand;
private T value;
}
public class FilterInfo {
private List<Filter> filters = new ArrayList<Filter>();
private String orderBy;
}
然后,在服务器上读取此JSON并构建查询应该是很好的
Gson gson = new GsonBuilder()
.setPrettyPrinting()
.setDateFormat(Constants.MY_DATE_FORMAT)
.create();
FilterInfo filterInfo = gson.fromJson(jsonString, FilterInfo.class);
不幸的是,Date
和Integer
值反序列化为String
和Double
我看到过使用TypeToken
的示例,自定义序列化程序/反序列化程序,但猜不出如何将它们应用于我
如果你能找出我的错误并提出好主意,我会很高兴的。
谢谢大家!
不幸的是,日期和整数值反序列化为String和Double
当您定义一个泛型类型字段(如字段
)时,Gson无法提供足够的信息,说明如何将某个值反序列化为某个类型。这是一个基本的限制:没有类型信息。因此,Gson解析
,就好像它被参数化为
。当考虑某个目标“slot”(列表元素、对象字段等)时,java.lang.object
,Gson根据值文本的类型解析JSON值:如果它类似于“…”
,那么它可能是字符串
;如果它类似于0
,那么它肯定是一个数字
,而且更准确:Double
(double是最大的标准数值——Gson只是在数字类型检测和解析上节省了时间+用户代码应该具有java.util.List
,并使用instanceof
检测特定的列表元素——它可能是整数、长值或双值——使用起来不太方便,因此java.lang.double
是默认策略)。因此,您可以使用字符串和双精度,而不是日期和整数:Gson simple本身无法获得所需的类型信息
为什么不能直接使用类型标记:类型标记用于为同一类型的元素指定类型参数,因此即使对于两个元素列表,也不能使用多个类型标记来覆盖不同的类型(列表类型标记为所有列表元素定义一种类型)
为了完成所需的工作,您可以创建一个类型适配器和相应的类型适配器工厂,以执行某种查找来解析具体类型
最终类过滤器TypeAdapterFactory
实现TypeAdapterFactory{
//这是一个符合您需要的策略:通过筛选对象内容解析java.lang.reflect.Type
私有最终函数>过滤器=空;
最终字符串orderBy=null;
}
在JSON类型名称策略中
如果您可以在JSON中提供类型名称来查找过滤器类型,那么示例JSON可能如下所示:
{
"filters": [
{"_type": "date", "fieldName": "fooDate", "operand": "=", "value": "1997-12-20"},
{"_type": "int", "fieldName": "barInteger", "operand": ">=", "value": 10}
],
"orderBy": "fooDate"
}
现在可以像这样构建Gson
实例:
private static final Gson Gson=new GsonBuilder()
.setDateFormat(“yyyy-MM-dd”)
.registerTypeAdapterFactory(getFilterTypeAdapterFactory)(jsonObject->{
如果(!jsonObject.has(“\u type”)){
返回defaultFilterType;
}
开关(jsonObject.get(“\u type”).getAsString()){
案例“int”:
返回integerFilterType;
案件“日期”:
返回日期过滤器类型;
违约:
返回defaultFilterType;
}
}))
.create();
替代战略
如果您不想增强JSON文档(这很好),那么您可以替换该策略,但是由于多种原因,解析类型可能会更复杂,因为它强烈地依赖于给定的筛选值名称(相同的名称可能用于不同的类型):
private static final Gson Gson=new GsonBuilder()
.setDateFormat(“yyyy-MM-dd”)
.registerTypeAdapterFactory(getFilterTypeAdapterFactory)(jsonObject->{
如果(!jsonObject.has(“fieldName”)){
返回defaultFilterType;
}
开关(jsonObject.get(“fieldName”).getAsString()){
案例“barInteger”:
返回integerFilterType;
案例“fooDate”:
返回日期过滤器类型;
违约:
返回defaultFilterType;
}
}))
.create();
请注意,TypeToken
s和Type
s可以被视为不可变和常量,因此可以将它们放在单独的类中:
最终类类型{
私有类型(){
}
静态最终类型defaultFilterType=new-TypeToken(){
}.getType();
静态最终类型integerFilterType=new-TypeToken(){
}.getType();
静态最终类型dateFilterType=new-TypeToken(){
}.getType();
}
现在,对于这两种策略,下面的代码
final FilterInfo FilterInfo=gson.fromJson(JSON,FilterInfo.class);
System.out.println(filterInfo.orderBy);
用于(最终过滤器:filterInfo.filters){
System.out.println(filter.fieldName+filter.operand+filter.value+“+filter.value.getClass()中的“);
}
将输出:
食物日期fooDate=1997年12月20日星期六00:00:00 EET类java.util.Date
Barintger>=10 of class java.lang.Integer
但是…你能帮我将lambda函数重构到Java 6吗?我是这样开始的…但无法完成。
function要将lamdas向后移植到Java 6,只需编写一个匿名内部类:new FilterTypeAdapterFactory(){…}
。然后,您将不再有getFilterTypeAdapterFactory
方法。您可以改为创建FilterTypeAdapterFactory
局部变量。@AzamatAlmukhametov匿名函数的主体是@SuppressWarnings(“未选中”)final TypeToken delegateTypeToken=(TypeToken)TypeToken.get(type);return gson.getDelegateAdapter(FilterTypeAdapterFactory.this,delegateTypeToken);
(注意FilterTypeAdapterFactory.this
--您可以“captu”
{
"filters": [
{"_type": "date", "fieldName": "fooDate", "operand": "=", "value": "1997-12-20"},
{"_type": "int", "fieldName": "barInteger", "operand": ">=", "value": 10}
],
"orderBy": "fooDate"
}
{
"filters": [
{"fieldName": "fooDate", "operand": "=", "value": "1997-12-20"},
{"fieldName": "barInteger", "operand": ">=", "value": 10}
],
"orderBy": "fooDate"
}