当前位置: 首页 > 知识库问答 >
问题:

使用Jackson在JAVA中生成自定义JSON模式

荣晨朗
2023-03-14

使用Jackson(最新版本可以)为JAVA bean/POJO类生成一个JSON模式,这样它就可以正确地包含嵌套对象的结构,并且还希望向嵌套POJO添加自定义属性(在我的例子中,希望为每个嵌套POJO参数添加一个完全分类的classname属性)。

用例-

比如说,我有一个Person类,如下所示。我用这个人作为我某个操作的参数。-

public class Person {

    private String name;
    private String id;
    private int i;
    private Person2 p;
    private List<String> strList;
    private HashMap<String, String> strMap;
    private Person3[] p3;

    public void setName(String name){
        this.name = name;
    }

    public void setId(String id){
        this.id = id;
    }

    public void setI(int i){
        this.i = i;
    }

    public void setP(Person2 p){
        this.p = p;
    }

    public String getName(){
        return this.name;
    }

    public String getId(){
        return this.id;
    }

    public int getI(){
        return this.i;
    }

    public Person2 getP(){
        return this.p;
    }

    public void setStrList(List<String> strList){
        this.strList = strList;
    }

    public List<String> getStrList(){
        return this.strList;
    }

    public void setStrMap(HashMap<String, String> strMap){
        this.strMap = strMap;
    }

    public HashMap<String, String> getStrMap(){
        return this.strMap;
    }

    public void setP3(Person3[] p3){
        this.p3 = p3;
    }

    public Person3[] getP3(){
        return this.p3;
    }
}
{
    "type": "object",
    "properties": {
        "name": {
            "type": "string"
        },
        "id": {
            "type": "string"
        },
        "i": {
            "type": "integer"
        },
        "p": {
            "type": "array",
            "items": {
                "type": "object",
                "properties": {
                    "name": {
                        "type": "string"
                    },
                    "id": {
                        "type": "string"
                    },
                    "i": {
                        "type": "integer"
                    },
                    "p1": {
                        "type": "object",
                        "properties": {
                            "name": {
                                "type": "string"
                            },
                            "id": {
                                "type": "string"
                            },
                            "i": {
                                "type": "integer"
                            }
                        }
                    }
                }
            }
        },
        "strList": {
            "type": "array",
            "items": {
                "type": "string"
            }
        },
        "strMap": {
            "type": "object"
        },
        "p3": {
            "type": "array",
            "items": {
                "type": "object",
                "properties": {
                    "name": {
                        "type": "string"
                    },
                    "id": {
                        "type": "string"
                    },
                    "i": {
                        "type": "integer"
                    }
                }
            }
        }
    },
    "classname": "com.agent.Person"
}

这个问题肯定与此相关--如何使用jackson遍历生成的json模式,并将自定义属性放入json模式中

共有1个答案

何聪
2023-03-14

这可以是上述问题的其中一种方法,可以如下所示-

这是我将类名放入生成的模式中的代码。此代码处理提供an数组或非数组参数时的情况。即可以成功处理Person.class和Person[].class。此代码无法处理在Jackson-https://github.com/fasterxml/jackson-databind/issues/339上仍然打开的self reference问题

下面的代码可以实例化如下-

public static void main(String[] args) throws IOException {
        ObjectMapper mapper = new ObjectMapper();
        Class<?> cls = Person[].class;
        if(cls.isArray()){
            cls = cls.getComponentType();
        }
        String s = "{\"rootNode\":{\"classname\":\"" + cls.getName() + "\"},"
                + getAttributeClassnames(cls) + "}";
        s = s.replace("\",}", "\"}").replace("},}", "}}");
        System.out.println(s);
        s = mapper.generateJsonSchema(cls).getSchemaNode().put("type", "array")
                .put("classnames", s).toString();
        s = s.replace("\\", "").replace("\"{", "{").replace("}\"", "}");        
        System.out.println(s);
    }

static String getAttributeClassnames(Class<?> cls) {
    String s = "";      
        Field[] field = cls.getDeclaredFields();
        int i = 0;
        while (i < field.length) {              
            if (!(field[i].getType() == Boolean.class)
                    && !(field[i].getType() == Integer.class)
                    && !(field[i].getType() == Character.class)
                    && !(field[i].getType() == Byte.class)
                    && !(field[i].getType() == Short.class)
                    && !(field[i].getType() == Long.class)
                    && !(field[i].getType() == Float.class)
                    && !(field[i].getType() == Double.class)
                    && !(field[i].getType().isPrimitive())
                    && !(field[i].getType() == String.class)
                    && !(Collection.class.isAssignableFrom(field[i]
                            .getType()))
                    && !(Map.class.isAssignableFrom(field[i].getType()))
                    && !(Arrays.class.isAssignableFrom(field[i].getType()))) {
                if(field[i].getType() == cls){
                    if (i == field.length - 1) {
                        Class<?> name = null;
                        if(field[i].getType().isArray()){
                            name = field[i].getType().getComponentType();
                        }else{
                            name = field[i].getType();
                        }
                        s = s + "\"" + field[i].getName() + "\""
                                + ":{\"classname\":\""
                                + name.getName() + "\","
                                +"}";
                    } else {
                        Class<?> name = null;                       
                        if(field[i].getType().isArray()){
                            name = field[i].getType().getComponentType();
                        }else{
                            name = field[i].getType();
                        }
                        s = s + "\"" + field[i].getName() + "\""
                                + ":{\"classname\":\""
                                + name.getName() + "\","
                                + "}" + ",";
                    }
                
                }else{
                    if (i == field.length - 1) {
                        Class<?> name = null;
                        if(field[i].getType().isArray()){
                            name = field[i].getType().getComponentType();
                        }else{
                            name = field[i].getType();
                        }
                        s = s + "\"" + field[i].getName() + "\""
                                + ":{\"classname\":\""
                                + name.getName() + "\","
                                + getAttributeClassnames(name)
                                + "}";
                    } else {
                        Class<?> name = null;                       
                        if(field[i].getType().isArray()){
                            name = field[i].getType().getComponentType();
                        }else{
                            name = field[i].getType();
                        }
                        s = s + "\"" + field[i].getName() + "\""
                                + ":{\"classname\":\""
                                + name.getName() + "\","
                                + getAttributeClassnames(name)
                                + "}" + ",";
                    }
                }
            }
            i++;
        }
    return s;
}
"classnames":{
          "<attribute_name>":{
                                "classname":"<classname>"
                             }
}
 类似资料:
  • 我试图用Jackson库创建复杂类的对象。每个对象都有一个模式,反序列化器需要使用该模式来解释JSON。我的问题是如何向反序列化器提供模式? 反序列化程序扩展了类JSONDeserializer,该类具有无参数构造函数和必须重写的抽象方法反序列化(解析器、上下文)。我想改用另一种方法反序列化(解析器、上下文、值),其中值是部分构造的对象,其中包括模式。也就是说,反序列化方法可以调用value。sc

  • 问题内容: 我正在使用Flickr API 。调用该方法时,默认的JSON结果为: 我想将此响应解析为Java对象: JSON属性应按以下方式映射: 不幸的是,我无法找到一种使用Annotations做到这一点的好方法。到目前为止,我的方法是将JSON字符串读入a 并从中获取值。 但是我认为,这是有史以来最不优雅的方式。有没有简单的方法,可以使用注释还是自定义反序列化器? 这对我来说将是很明显的,

  • 我正在使用Swashback为ASP生成swagger文档。NET核心API我正在写。在我的API中,我使用了许多自定义Json转换器,因此我接收和返回的Json看起来与C类的定义不完全一样。例如,我可能有这样一个类: 它将被序列化为 然而,Swashuckle将其记录为 我如何告诉Swashback我的模型是如何序列化和反序列化的?

  • 问题内容: 我想在Eclipse中生成自定义方法,就像我们可以生成toString,getter和沉降器的方式一样(右键单击-> source->)。谁能告诉我这样做涉及什么? 谢谢, 荷兰人 问题答案: 您可以在最近(Eclipse Galileo 3.5)生成动作之后添加自己的动作, 使用主动贡献URI: 具有活动操作定义标识符: 使用有效贡献项目类:(包) 来自贡献插件:org.eclips

  • 我们有一个用例,在这个用例中,我们定义了许多不同的RPC。我们使用google的protobuf java生成了一个基于java的grpc存根代码 要转换为like 在java生成的代码中,每个原始服务应该有2个服务。我们只希望最终java生成的代码具有2个服务,解析器可能会/可能不会更新原始服务。原型文件。 当前protoc是否可以进行这种定制?我们可以扩展插件并编写我们的插件吗-