如何减少自定义反序列化器中的 if 数量

How to reduce number of if's in custom deserializer

我用 SonarLint 分析了我的自定义 JSON 反序列化器,它说我应该将认知复杂度从 21 降低到至少 15。换句话说,这意味着我必须有很多 if 语句。我的反序列化器如下所示:

   @Override
    public Movie deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
        ObjectCodec oc = p.getCodec();
        JsonNode node = oc.readTree(p);

        Movie movie = new Movie();
        movie.setId(node.get("id").textValue());
        movie.setTitle(node.get("movieInfo").get("title").textValue());

        int identifiersSize = node.get("movieInfo").get("identifiers").size();
        String IMSC="";
        for(int i=0;i<identifiersSize;i++){
            if(node.get("movieInfo").get("identifiers").get(i).get("type").textValue().equals("IMSC")){
                IMSC = node.get("movieInfo").get("identifiers").get(i).get("identifier").textValue();
            }
        }
        if(IMSC.isEmpty()){
            IMSC = node.get("id").textValue();
        }
        movie.setIMSC(IMSC);

        if(node.get("movieInfo").has("subtitle")){
            movie.setSubtitle(node.get("movieInfo").get("subtitle").textValue());
        }

        if(node.get("movieInfo").has("publishedDate")){
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
            LocalDate date;
            try {
                date = LocalDate.parse(node.get("movieInfo").get("publishedDate").asText(), formatter);
            } catch (DateTimeParseException e){
                date = LocalDate.of(node.get("movieInfo").get("publishedDate").asInt(),1,1);
            }
            movie.setPublishedDate(date);
        }


        if(node.get("movieInfo").has("publisher")){
            movie.setPublisher(node.get("movieInfo").get("publisher").textValue());
        }

        if(node.get("movieInfo").has("description")){
            movie.setDescription(node.get("movieInfo").get("description").textValue());
        }

        if(node.get("movieInfo").has("length")){
            movie.setLength(node.get("movieInfo").get("length").asInt());
        }

        if(node.get("movieInfo").has("imageLinks")){
            movie.setThumbnailUrl(node.get("movieInfo").get("imageLinks").get("thumbnail").asText());
        }

        if(node.get("movieInfo").has("language")){
            movie.setLanguage(node.get("movieInfo").get("language").asText());
        }

        if(node.get("movieInfo").has("previewLink")){
            movie.setPreviewLink(node.get("movieInfo").get("previewLink").asText());
        }

        if(node.get("movieInfo").has("ratingsCount")) {
            movie.setRatingsCount(node.get("movieInfo").get("ratingsCount").asInt());
            movie.setAverageRating(node.get("movieInfo").get("averageRating").doubleValue());
        }


        if(node.get("movieInfo").has("authors")) {
            List<String> authors= new ArrayList<>();
            int size = node.get("movieInfo").get("authors").size();
            for(int i =0;i<size;i++){
               authors.add(node.get("movieInfo").get("authors").get(i).asText());
            }
            movie.setAuthors(authors);
        }

        if(node.get("movieInfo").has("categories")) {
            List<String> categories= new ArrayList<>();
            int size = node.get("movieInfo").get("categories").size();
            for(int i =0;i<size;i++){
            categories.add(node.get("movieInfo").get("categories").get(i).asText());
            }
            movie.setCategories(categories);
        }

        return movie;
    }

我的问题是:有更好的方法吗?我希望 SonarLint 的错误为零。

您似乎多次致电 node.get("movieInfo")node.get("id")。您可以通过在局部变量中缓存这两个调用的值来大大简化代码。

但我认为没有好的 方法可以大幅减少if 语句。 (您可以通过创建 lambda 的 table 然后迭代节点的 "keys",查找并调用相应的 lambda 来减少 if 语句。但我怀疑这会使代码更易于阅读。)

您可以将方法拆分为子方法并减少每个方法的 if 语句数。这可能会使 SonarLint 更快乐,但它使代码更具可读性是 debatable。


I would like to have zero errors from SonarLint.

这不是您的目标。 SonarLint 等工具表面上的目的是通过人为衡量代码复杂性来帮助您提高代码的可读性和可维护性。然而:

  • 程序员通常可以处理这里显示的那种复杂性。此代码重复性大于复杂性。
  • 有时复杂性是您尝试执行的任务所固有的。