Java JSON查询过滤器传输

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

我想以JSON的形式从客户机传输到服务器WHERE子句。 我已在服务器上创建了
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"
}