java json过滤_java – JSON查询过滤器传输

Unfortunately, Date and Integer values deserialize as String and Double.

当您定义类似Field< T>的泛型类型字段时 – Gson无法获得关于如何将某个值反序列化为某种类型的足够信息.这是一个基本的限制:没有类型信息.因此,Gson解析了< T>.好像它被参数化为< Object>.当某个目标“slot”(列表元素,对象字段等)被认为是java.lang.Object时,Gson根据值文字的类型解析一个JSON值:如果它类似于“…”,则它是可能是字符串;如果它是0,那么它肯定是一个数字,更准确:双(双精度是最大的标准数值–Gson只是节省了数字类型检测的时间,解析用户代码应该有java.util.List< Number>并使用instanceof检测特定的列表元素 – 它可能是一个整数,一个long或double值 – 使用起来不是很方便,因此java.lang.Double是默认策略).所以你有字符串和双精度而不是日期和整数:Gson simple本身不能拥有你想要的类型信息.

为什么不能直接使用类型标记:类型标记用于为相同类型的元素指定类型参数,因此即使对于双元素列表,也不能有多个类型标记来覆盖不同类型(列表类型标记为所有类型定义类型列表元素).

要完成您的需要,您可以创建一个类型适配器和相应的类型适配器工厂来执行某种查找以解决具体类型.说,

final class FilterTypeAdapterFactory

implements TypeAdapterFactory {

// This is a strategy up to your needs: resolve a java.lang.reflect.Type by a filter object content

private final Function super JsonObject, ? extends Type> typeResolvingStrategy;

private FilterTypeAdapterFactory(final Function super JsonObject, ? extends Type> typeResolvingStrategy) {

this.typeResolvingStrategy = typeResolvingStrategy;

}

static TypeAdapterFactory getFilterTypeAdapterFactory(final Function super JsonObject, ? extends Type> typeResolvingStrategy) {

return new FilterTypeAdapterFactory(typeResolvingStrategy);

}

@Override

public TypeAdapter create(final Gson gson, final TypeToken typeToken) {

// Is it the Filter class?

if ( Filter.class.isAssignableFrom(typeToken.getRawType()) ) {

// Get the JsonObject type adapter

final TypeAdapter jsonObjectTypeAdapter = gson.getAdapter(JsonObject.class);

// This is a function to resolve a downstream type adapter by the given type

// If a downstream parser is not used, then the lookup will end up with self-recursion...

final Function> typeTypeAdapterFunction = type -> {

// Create a type token dynamically

@SuppressWarnings("unchecked")

final TypeToken delegateTypeToken = (TypeToken) TypeToken.get(type);

// And get the downstream type adapter

return gson.getDelegateAdapter(this, delegateTypeToken);

};

return new FilterTypeAdapter<>(jsonObjectTypeAdapter, typeTypeAdapterFunction, typeResolvingStrategy);

}

// Not a thing we can handle? Return null, and Gson will try to perform lookup itself

return null;

}

private static final class FilterTypeAdapter

extends TypeAdapter {

private final TypeAdapter jsonObjectTypeAdapter;

private final Function super Type, ? extends TypeAdapter> typeAdapterResolver;

private final Function super JsonObject, ? extends Type> typeResolvingStrategy;

private FilterTypeAdapter(

final TypeAdapter jsonObjectTypeAdapter,

final Function super Type, ? extends TypeAdapter> typeAdapterResolver,

final Function super JsonObject, ? extends Type> typeResolvingStrategy

) {

this.jsonObjectTypeAdapter = jsonObjectTypeAdapter;

this.typeAdapterResolver = typeAdapterResolver;

this.typeResolvingStrategy = typeResolvingStrategy;

}

@Override

public void write(final JsonWriter out, final T value) {

// If you ever need it, then you have to implement it

throw new UnsupportedOperationException();

}

@Override

public T read(final JsonReader in)

throws IOException {

// Read the next {...} and convert it to JsonObject

final JsonObject jsonObject = jsonObjectTypeAdapter.read(in);

// Now resolve a real type by the given JsonObject instance

// ... and resolve its type adapter

final TypeAdapter delegateTypeAdapter = typeAdapterResolver.apply(typeResolvingStrategy.apply(jsonObject));

// Since the reader has the {...} value already consumed, we cannot read it at this moment

// But we can convert the cached JsonObject to the target type object

return delegateTypeAdapter.fromJsonTree(jsonObject);

}

}

}

好的,如何使用它?我用以下映射测试了它:

final class Filter {

final String fieldName = null;

final String operand = null;

final T value = null;

}

final class FilterInfo {

final List> filters = null;

final String orderBy = null;

}

In-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 -> {

if ( !jsonObject.has("_type") ) {

return defaultFilterType;

}

switch ( jsonObject.get("_type").getAsString() ) {

case "int":

return integerFilterType;

case "date":

return dateFilterType;

default:

return defaultFilterType;

}

}))

.create();

替代战略

如果您不想增强JSON文档(那很好),那么您可以只替换策略,但是由于几个原因,解析类型可能会更复杂,因为它强烈依赖于给定的过滤器值名称(同名)可能用于不同的类型):

{

"filters": [

{"fieldName": "fooDate", "operand": "=", "value": "1997-12-20"},

{"fieldName": "barInteger", "operand": ">=", "value": 10}

],

"orderBy": "fooDate"

}

private static final Gson gson = new GsonBuilder()

.setDateFormat("yyyy-MM-dd")

.registerTypeAdapterFactory(getFilterTypeAdapterFactory(jsonObject -> {

if ( !jsonObject.has("fieldName") ) {

return defaultFilterType;

}

switch ( jsonObject.get("fieldName").getAsString() ) {

case "barInteger":

return integerFilterType;

case "fooDate":

return dateFilterType;

default:

return defaultFilterType;

}

}))

.create();

请注意,TypeTokens和Types可以被认为是不可变的和常量的,因此它们可以放在一个单独的类中:

final class Types {

private Types() {

}

static final Type defaultFilterType = new TypeToken>() {

}.getType();

static final Type integerFilterType = new TypeToken>() {

}.getType();

static final Type dateFilterType = new TypeToken>() {

}.getType();

}

现在,对于两个stragies,以下代码

final FilterInfo filterInfo = gson.fromJson(JSON, FilterInfo.class);

System.out.println(filterInfo.orderBy);

for ( final Filter filter : filterInfo.filters ) {

System.out.println(filter.fieldName + filter.operand + filter.value + " of " + filter.value.getClass());

}

将输出:

fooDate fooDate=Sat Dec 20 00:00:00 EET 1997 of class java.util.Date barInteger>=10 of class java.lang.Integer

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值