joelittlejohn / jsonschema2pojo

Generate Java types from JSON or JSON Schema and annotate those types for data-binding with Jackson, Gson, etc
http://www.jsonschema2pojo.org
Apache License 2.0
6.24k stars 1.66k forks source link

Could not find a way to generate all classes from schema "definitions" #1511

Closed grobitto closed 1 year ago

grobitto commented 1 year ago

Hi all!

I have a json schema without root element, just a bunch of objects inside "definitions". Is there a way to generate java classes for every schema definition? This schema was auto-generated from typescript sources I want to mirror in my java app. I tried to modify schema, added "$ref":"#/definitions/Root" at the top level, but this way only Root graph gets generated,

Example schema:

{
    "$schema": "http://json-schema.org/draft-07/schema#",
    "definitions": {
        "Root": {
            "properties": {
                "image": {
                    "$ref": "#/definitions/Image"
                },
                "title": {
                    "type": "string"
                },
                "type": {
                    "type": "string"
                }
            },
            "type": "object"
        },
        "Image": {
            "properties": {
                "id": {
                    "type": "integer"
                }
            },
            "type": "object"
        },
        "Root2": {
            "properties": {
                "id": {
                    "type": "integer"
                }
            },
            "type": "object"
        }
    }
}
ArtisanDejure commented 1 year ago

I was able to get this to work by following the example here: https://stackoverflow.com/questions/60478946/maven-plugin-jsonschema2pojo-maven-plugin-not-generating-pojos-for-all-the-defin

I did create the main class used in the plugin in a different maven module as opposed to a whole new project. At first I tried putting it in the same project, but of course the code has to be compiled before it can be used in a maven goal running in generate-sources.

grobitto commented 1 year ago

Yep, it worked after a little modification of the example you provided. Here is the full code:

import java.util.HashSet;
import java.util.Iterator;

import org.jsonschema2pojo.Annotator;
import org.jsonschema2pojo.GenerationConfig;
import org.jsonschema2pojo.Schema;
import org.jsonschema2pojo.SchemaStore;
import org.jsonschema2pojo.rules.Rule;
import org.jsonschema2pojo.rules.RuleFactory;
import org.jsonschema2pojo.rules.SchemaRule;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.sun.codemodel.JClassContainer;
import com.sun.codemodel.JType;

public class JsonSchemaRuleFactory extends RuleFactory {

    public JsonSchemaRuleFactory() {
    };

    public JsonSchemaRuleFactory(GenerationConfig generationConfig, Annotator annotator, SchemaStore schemaStore) {
        super(generationConfig, annotator, schemaStore);
    }

    @Override
    public Rule<JClassContainer, JType> getSchemaRule() {
        return new MySchemaRule(this);
    }

    private HashSet<String> processed = new HashSet<>();

    private class MySchemaRule extends SchemaRule {

        public MySchemaRule(JsonSchemaRuleFactory jsonSchemaRuleFactory) {
            super(jsonSchemaRuleFactory);
        }

        @Override
        public JType apply(String nodeName, JsonNode schemaNode, JsonNode parent, JClassContainer generatableType, Schema schema) {
            final JType apply = super.apply(nodeName, schemaNode, parent, generatableType, schema);
            final JsonNode definitions = schemaNode.get("definitions");

            if (definitions != null && definitions.isObject()) {
                ObjectNode objectNode = (ObjectNode) definitions;
                final Iterator<String> nodeIterator = objectNode.fieldNames();

                while (nodeIterator.hasNext()) {
                    final String name = nodeIterator.next();

                    try {
                        final ObjectNode node = (ObjectNode) objectNode.get(name);
                        final Schema currentSchema = getSchemaStore().create(schema, "#/definitions/" + name,
                                getGenerationConfig().getRefFragmentPathDelimiters());

                        if (currentSchema.isGenerated()) {
                            continue;
                        }
                        super.apply(name, node, schemaNode, generatableType.getPackage(), currentSchema);

                    } catch (Exception e) {
                        e.printStackTrace();
                    }

                }
            }

            return apply;
        }
    }
}