Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/304.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 代码设计:从套接字到自定义处理程序类的JSON_Java_Json_Generics_Gson_Guice - Fatal编程技术网

Java 代码设计:从套接字到自定义处理程序类的JSON

Java 代码设计:从套接字到自定义处理程序类的JSON,java,json,generics,gson,guice,Java,Json,Generics,Gson,Guice,我有一个Java的套接字服务器。此套接字将接收具有特定结构的json字符串 { "command": "test", "name": "Hallo Welt" } 我不能改变这种结构。“command”的值将声明内容的类型 从套接字接收到该命令后,我想调用不同的处理程序来处理这些不同的命令: 命令“test”>TestHandler实现CommandHandler 命令“foo”>foodhandler实现CommandHandler 如何将json转换为对象并将该对象绑定

我有一个Java的套接字服务器。此套接字将接收具有特定结构的json字符串

{
    "command": "test",
    "name": "Hallo Welt"
}
我不能改变这种结构。“command”的值将声明内容的类型

从套接字接收到该命令后,我想调用不同的处理程序来处理这些不同的命令:

  • 命令“test”>TestHandler实现CommandHandler
  • 命令“foo”>foodhandler实现CommandHandler
如何将json转换为对象并将该对象绑定到特定的处理程序?

这是我目前的做法: 我有一个名为BaseCommand的模型类,它包含一个enum命令字段

class BaseCommand {
    public CommandType command;
}

class TestCommand extends BaseCommand {
    public String name;
}
使用GSON,我将JSON解析为BaseCommand类。 之后,我可以读取命令类型

我声明一个枚举以将命令类型映射到处理程序:

enum CommandType {
    test(TestHandler.class),
    foo(FooHandler.class);

    public final Class<? extends CommandHandler> handlerClass;        

    public CommandTypes(Class<? extends CommandHandler> handlerClass) {
        this.handlerClass = handlerClass;
    }
}
enum命令类型{
test(TestHandler.class),
foo(foodhandler.class);
公开期末班
如何获取CommandModel?
如果commandType为“test”,如何自动解析TestCommand

您可以使用
TypeAdapterFactory
以最准确和灵活的方式获取最合适的类型适配器。下面的示例与您的类命名略有不同,但我认为这对您来说不是什么大问题。因此,假设您有以下命令参数DTO声明:

抽象类AbstractCommandDto{
最终字符串命令=null;
}
最终类HelloCommandDto
将命令扩展到{
最终字符串名称=null;
}
现在,您可以创建一个特殊的
TypeAdapterFactory
,通过命令参数名称预先确定传入的命令。它可能看起来很复杂,但实际上
TypeAdapterFactory
ies并不是很难实现。请注意,
JsonDeserializer
可能是您的另一个选项,但您会失败自动反序列化,除非您将其
反序列化()
方法委托给另一个备份
Gson
实例

final类AbstractCommandToTypeAdapterFactory
实现TypeAdapterFactory{
//工厂不处理任何状态,可以实例化一次
私有静态最终类型适配器工厂AbstractCommandtTypeAdapterFactory=新的AbstractCommandtTypeAdapterFactory();
//类型标记用于定义类型信息,是完美的值类型,因此它们也可以实例化一次
私有静态最终类型令牌abstractCommandProbingDtoTypeToken=新类型令牌(){
};
私有静态最终类型令牌HelloCommand和DtoTypeToken=新类型令牌(){
};
私有AbstractCommandTypeAdapterFactory(){
}
静态TypeAdapterFactory GetAbstractCommandToTypeAdapterFactory(){
返回AbstractCommandToTypeAdapterFactory;
}
@凌驾
公共类型适配器创建(最终Gson Gson、最终TypeToken TypeToken){
//首先,检查传入类型是否为AbstractCommandDto
if(AbstractCommandTo.class.isAssignableFrom(typeToken.getRawType())){
//如果是,则为混凝土类型构建一个特殊类型适配器
最终类型适配器AbstractCommandtTypeAdapter=新的AbstractCommandtTypeAdapter(
格森,
getDelegateAdapter(这是abstractCommandProbingDtoTypeToken),
(commandName,jsonObject)->反序列化(gson,commandName,jsonObject),
dto->getTypeAdapter(gson,dto)
);
//javac的一些欺骗行为。。。
@抑制警告(“未选中”)
final TypeAdapter TypeAdapter=(TypeAdapter)AbstractCommandToTypeAdapter;
返回类型适配器;
}
//如果是其他原因,就让Gson选择下一个类型适配器
返回null;
}
//从一个随时可用的JsonObject创建一个AbstractCommandDto实例(参见下面关于JSON树的缺点)
要反序列化的私有AbstractCommandDto(最终Gson Gson、最终字符串commandName、最终JsonObject JsonObject){
@抑制警告(“未选中”)
最终的TypeToken TypeToken=(TypeToken)解析(commandName);
final-TypeAdapter-TypeAdapter=gson.getDelegateAdapter(这个,typeToken);
从JSONTREE(jsonObject)返回typeAdapter.fromJsonTree;
}
私有类型适配器getTypeAdapter(最终Gson Gson,最终AbstractCommandDto dto){
@抑制警告(“未选中”)
最终类clazz=(类)dto.getClass();
返回gson.getDelegateAdapter(this,TypeToken.get(clazz));
}
//这只是为了简单起见,甚至可以从类型适配器工厂类的其他地方提取
私有静态TypeToken,Consumer>commandRegistry=new LinkedHashMap();
commandRegistry.put(HelloCommandDto.class,新的HelloCommand());
//模拟并接受请求
final AbstractCommandDto AbstractCommandDto=gson.fromJson(“{\”命令\“:\”你好\“,”名字\“:\”世界\“}”,AbstractCommandDto.class);
//解析命令
最终使用者命令=commandRegistry.get(abstractCommandDto.getClass());
如果(命令==null){
抛出新的IllegalArgumentException(“无法处理”+AbstractCommandTo.command);
}
//派遣
@抑制警告(“未选中”)
最终使用者命令=(使用者)命令;
接受(abstractCommandDto);
//模拟反应
System.out.println(gson.toJson(abstractCommandDto));
}
私有静态最终类HelloCommand
实施消费者{
@凌驾
公共无效接受(最终Hello命令至Hello命令){
System.out.println(“Hallo”+helloCommandDto.name);
}
}
输出:

哈罗贴边

public interface CommandHandler<T extends BaseCommand> {
    void handle(T command);
}
// in class ...
private final Map<CommandType, CommandHandler> handlers;

@Inject ClassName(Map<CommandType, CommandHandler> handlers) {
    this.handlers = handlers;
}

// in converter method
private void convert(String json) {
    BaseCommand baseCommand = GSONHelper().fromJson(json, BaseCommand.class);

    // How can I get the CommandModel? 
    // If the commandType is "test" how can I parse TestCommand automatically?

    ??? commandModel = GSONHelper().fromJson(json, ???);

    handlers.get(baseCommand.command).handle(commandModel);
}