maven 从Json模式生成记录

m4pnthwp  于 11个月前  发布在  Maven
关注(0)|答案(1)|浏览(113)

对于我的许多项目,我喜欢使用org.jsonschema2pojo.jsonschema2pojo-maven-plugin maven插件,以便从JSON模式文件生成一些POJO类。这很好用,节省了我编写样板代码的时间。
然而,我经常把这些类作为最终的和不可变的,所以我希望能够生成Java记录,这样我就可以强制执行这些限制,并获得沿着而来的性能增强记录。我已经通过了documentationGitLab repo,但我没有看到任何方法来做到这一点与这个特定的插件。
是不是我错过了什么,或者有其他插件或库提供这种能力?
编辑:假设我已经做了我的研究,Java记录实际上是我想要/需要的。我不想要可变性,我不想要可扩展性,我可以公开成员字段,我想提高比较操作(.equals)的性能,我想利用模式匹配。

velaa5lx

velaa5lx1#

我会避免使用记录,这不仅是因为它们应该只存储一些值,还因为它们没有与传统类相同的控制级别。
下面这篇文章把这一切都分解了:
https://www.baeldung.com/java-record-vs-lombok
使用Jackson的@JsonProperty注解,可以告诉序列化器/反序列化器如何将每个键Map到适当的字段。
如果生成类存根并添加一些Lombok,则可以简化此过程。
下面的JSON:

/** https://json.org/example.html */
{
  "glossary": {
    "title": "example glossary",
    "GlossDiv": {
      "title": "S",
      "GlossList": {
        "GlossEntry": {
          "ID": "SGML",
          "SortAs": "SGML",
          "GlossTerm": "Standard Generalized Markup Language",
          "Acronym": "SGML",
          "Abbrev": "ISO 8879:1986",
          "GlossDef": {
            "para": "A meta-markup language, used to create markup languages such as DocBook.",
            "GlossSeeAlso": ["GML", "XML"]
          },
          "GlossSee": "markup"
        }
      }
    }
  }
}

字符串
转换为以下形状:

package org.example.json;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;

import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.Data;

public class GenerateClasses {
    private static final ObjectMapper om = new ObjectMapper();
    private static final ClassLoader classLoader = GenerateClasses.class.getClassLoader();

    public static void main(String[] args) {
        try (InputStream is = classLoader.getResourceAsStream("glossary.json")) {
            Root root = om.readValue(is, Root.class);
            System.out.println(root); // Object::toString
            System.out.println(om.writerWithDefaultPrettyPrinter().writeValueAsString(root));
        } catch (IOException e) {
            System.out.println("Failed to read JSON");
        }
    }

    @Data
    public static class Glossary {
        private String title;
        @JsonProperty("GlossDiv")
        private GlossDiv glossDiv;
    }

    @Data
    public static class GlossDef {
        private String para;
        @JsonProperty("GlossSeeAlso")
        private List<String> glossSeeAlso; /* Changed from ArrayList */
    }

    @Data
    public static class GlossDiv {
        private String title;
        @JsonProperty("GlossList")
        private GlossList glossList;
    }

    @Data
    public static class GlossEntry {
        @JsonProperty("ID")
        private String id; /* Manually changed from 'iD' */
        @JsonProperty("SortAs")
        private String sortAs;
        @JsonProperty("GlossTerm")
        private String glossTerm;
        @JsonProperty("Acronym")
        private String acronym;
        @JsonProperty("Abbrev")
        private String abbrev;
        @JsonProperty("GlossDef")
        private GlossDef glossDef;
        @JsonProperty("GlossSee")
        private String glossSee;
    }

    @Data
    public static class GlossList {
        @JsonProperty("GlossEntry")
        private GlossEntry glossEntry;
    }

    @Data
    public static class Root {
        private Glossary glossary;
    }
}


我使用以下工具生成了上面的代码:
https://json2csharp.com/code-converters/json-to-pojo(选择JSON > Java)
我添加了Lombok @Data注解,将所有字段设置为private,并修改了标注的字段。

Jackson+唱片公司声明

请注意,Jackson2.11.4以下的版本在使用记录格式化JSON时会遇到问题:
https://dev.to/brunooliveira/practical-java-16-using-jackson-to-serialize-records-4og4
以下修改后的程序(从上面开始)使用记录代替与Lombok混合的类。它不再依赖于Lombok。

package org.example.json;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;

import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.ObjectMapper;

public class GenerateClasses {
    private static final ObjectMapper om = new ObjectMapper();
    private static final ClassLoader classLoader = GenerateClasses.class.getClassLoader();

    public static void main(String[] args) {
        try (InputStream is = classLoader.getResourceAsStream("glossary.json")) {
            Root root = om.readValue(is, Root.class);
            System.out.println(root); // Object::toString
            System.out.println(om.writerWithDefaultPrettyPrinter().writeValueAsString(root));
        } catch (IOException e) {
            System.out.println("Failed to read JSON");
            System.err.println(e);
        }
    }

    public record Glossary (
        String title,
        @JsonProperty("GlossDiv")
        GlossDiv glossDiv
    ) {}

    public record GlossDef (
        String para,
        @JsonProperty("GlossSeeAlso")
        List<String> glossSeeAlso /* Changed from ArrayList */
    ) {}

    public record GlossDiv (
        String title,
        @JsonProperty("GlossList")
        GlossList glossList
    ) {}

    public record GlossEntry (
        @JsonProperty("ID")
        String id, /* Manually changed from 'iD' */
        @JsonProperty("SortAs")
        String sortAs,
        @JsonProperty("GlossTerm")
        String glossTerm,
        @JsonProperty("Acronym")
        String acronym,
        @JsonProperty("Abbrev")
        String abbrev,
        @JsonProperty("GlossDef")
        GlossDef glossDef,
        @JsonProperty("GlossSee")
        String glossSee
    ) {}

    public record GlossList (
        @JsonProperty("GlossEntry")
        GlossEntry glossEntry
    ) {}

    public record Root (
        Glossary glossary
    ) {}
}


如果遇到以下异常,则需要更新Jackson依赖项:
com.fasterxml.jackson.databind.exc.InvalidDefinitionException:无法构造org.example.json.GenerateClasses$Root的示例(不存在创建者,与默认构造一样):无法从Object值进行转换(没有基于委托或属性的创建者)
at [源:(BufferedInputStream);第2行,第3列]

相关问题