Java 检测字符串的有效方法?

Java 检测字符串的有效方法?,java,json,deserialization,gson,Java,Json,Deserialization,Gson,我正在从事一个项目,在该项目中,我正在使用运行restful服务的RestTemplate调用我的一个服务器,并从它们那里获得响应 如果出现问题,我将从服务器得到的响应可以是这些错误响应中的任何一个(这就是我对错误响应的全部内容)—— {"warning": "user_id not found", "user_id": some_user_id} {"error": "user_id for wrong partition", "user_id": some_user_id, "partiti

我正在从事一个项目,在该项目中,我正在使用运行restful服务的
RestTemplate
调用我的一个服务器,并从它们那里获得响应

如果出现问题,我将从服务器得到的响应可以是这些错误响应中的任何一个(这就是我对错误响应的全部内容)——

{"warning": "user_id not found", "user_id": some_user_id}
{"error": "user_id for wrong partition", "user_id": some_user_id, "partition": some_partition}
{"error": "missing client id", "client_id":2000}
或者低于成功响应(可以是任意随机的json字符串键,也可以是不同的)——

  • 如果我得到上面提到的任何错误响应,那么我将对其进行反序列化(my bad:(),这样我就可以使用特定的
    错误
    警告
    将它们记录为错误,例如,
    找不到用户id
    缺少客户端id
  • 如果它是一个成功的响应,那么我也反序列化它,我的用例不需要它,因为我们没有任何POJO,我只需要返回我从服务器得到的响应
  • 在我的用例中,如果响应是成功的,我不需要反序列化响应字符串,因为我们没有任何POJO,并且我们返回从服务器获得的响应字符串。但只用于记录特定的错误消息(如果我从服务器获得错误响应)我正在反序列化它,我认为这是不必要的。对于我的用例可能有更好的解决方案

    下面是我的Java客户端,它正在使用
    future.get调用
    Callable
    任务-

    public class TestingClient implements IClient {
    
        private ExecutorService service = Executors.newFixedThreadPool(10);
        private RestTemplate restTemplate = new RestTemplate();
    
        @Override
        public String executeSync(ClientKey keys) {
    
            String response = null;
            try {
    
                ClientTask ClientTask = new ClientTask(keys, restTemplate);
                Future<String> future = service.submit(ClientTask);
                response = handle.get(keys.getTimeout(), TimeUnit.MILLISECONDS);
            } catch (TimeoutException e) {
    
            } catch (Exception e) {
    
            }
    
            return response;
        }
    }
    
    正如您在我上面的代码中所看到的,如果我们得到任何错误响应,我们反序列化JSON字符串只是为了记录特定的错误消息。但是为了成功响应,我们不需要任何反序列化,但我们仍然在这样做

    有没有更好的方法来解决这个问题?因为目前我发现GSON反序列化存在一些性能问题

    识别成功响应和错误响应的唯一方法是在响应中使用
    error
    warning
    ,因此我考虑使用正则表达式,可以将错误或警告识别为响应字符串中的键。如果响应字符串中包含错误或警告,则提取特定错误或警告消息,并将其记录下来。但不确定这是否会对性能有任何好处


    有没有其他更好的方法来解决这个问题而不使用GSON反序列化。

    您不需要反序列化到POJO

    一个简单的JSON解析器(如在上找到的解析器)将提供最小的JSON解析,并返回一个您可以查询的JSONObject

    我非常怀疑这一点

    • 您可以使用正则表达式或其他方式更快地解析json响应,而不必冒在极端情况下失败的风险
    • 考虑到响应字符串的大小,JSON解析是代码中的性能瓶颈

    除非您做了一些认真的分析,否则我会谨慎行事,并遵循

    这是一个很好的做法,在您的响应中使用HTTP状态代码(例如,BAD_请求,NOT_FOUND)。从服务器返回其中一个,然后检查客户端。仅当返回一些错误代码时,才允许解析响应:

    String result = restTemplate.execute("url", HttpMethod.GET, null, new HttpMessageConverterExtractor<String> {
            @Override
            public MyEntity extractData(ClientHttpResponse response)
            throws IOException {
                String result = super.extractData(response);
                if (response.getStatusCode() != HttpStatus.OK) {
                    // parse message and log only for some error code
                    JsonObject errorJson = parse(result);
                    log.warn("Got {} status error, with message [{}]", response.getStatusCode(), errorJson.get("warning"));
                } 
                return result;
            }
    
        });
    
    String result=restemplate.execute(“url”),HttpMethod.GET,null,新的HttpMessageConverterExtractor{
    @凌驾
    公共MyEntity提取数据(ClientHttpResponse响应)
    抛出IOException{
    字符串结果=super.extractData(响应);
    if(response.getStatusCode()!=HttpStatus.OK){
    //仅分析某些错误代码的消息和日志
    JsonObject errorJson=parse(结果);
    log.warn(“Got{}status error,带有消息[{}]”,response.getStatusCode(),errorJson.get(“warning”);
    } 
    返回结果;
    }
    });
    
    Java的JSON库很多,建议您也在这篇文章中看很多主题:我很好奇您的“性能问题”是什么撇开这一点不谈,您可以简单地使用Gson的
    JsonParser
    类解析JSON,然后直接处理解析树对象,而不是反序列化到POJO。正则表达式比简单的线性解析要昂贵得多。@BrianRoach:您是说我不应该使用
    Gson.fromJson
    方法我的用例,因为它将反序列化到POJO。我不确定Gson
    JsonParser
    ,你能提供一个使用JsonParser的示例基础吗。这会让我更好地理解。如果你上面代码中的
    JsonObject
    是一个
    com.google.Gson.JsonObject
    ,而不是你自己的POJO,那么所做的就是解析JSON并将其粘贴在对象内部的
    映射中。不太可能在那里发现任何“性能问题”(鉴于JSON的尺寸很小,您自己也不太可能更快地完成此操作)
    
    class ClientTask implements Callable<String> {
    
        private ClientKey cKeys;
        private RestTemplate restTemplate;
    
        public ClientTask(ClientKey cKeys, RestTemplate restTemplate) {
            this.restTemplate = restTemplate;
            this.cKeys = cKeys;
        }
    
        @Override
        public String call() throws Exception {
    
            // .. some code here
            String url = "some_url";            
            String response = restTemplate.getForObject(url, String.class);
    
            String test = checkJSONResponse(response);
    
            return test;
        }
    
        private String checkJSONResponse(final String response) throws Exception {
    
            // may be there are some better way of doing it for my scenario instead of using GSON
            Gson gson = new Gson();
            String str = null;
            JsonObject jsonObject = gson.fromJson(response, JsonObject.class); // parse it, may be performance issues here/
            if (jsonObject.has("error") || jsonObject.has("warning")) {
    
            final String error = jsonObject.get("error") != null ? jsonObject.get("error").getAsString() : jsonObject
            .get("warning").getAsString();
    
            // log specific `error` here using log4j
            str = response;
            } else {
                str = response;
            }
    
            return str;
        }
    }
    
    String result = restTemplate.execute("url", HttpMethod.GET, null, new HttpMessageConverterExtractor<String> {
            @Override
            public MyEntity extractData(ClientHttpResponse response)
            throws IOException {
                String result = super.extractData(response);
                if (response.getStatusCode() != HttpStatus.OK) {
                    // parse message and log only for some error code
                    JsonObject errorJson = parse(result);
                    log.warn("Got {} status error, with message [{}]", response.getStatusCode(), errorJson.get("warning"));
                } 
                return result;
            }
    
        });