Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature request] Allow javaInterfaces to be passed as plugin configuration #1526

Closed
antssilva96 opened this issue Jun 1, 2023 · 4 comments

Comments

@antssilva96
Copy link

antssilva96 commented Jun 1, 2023

We're using this plugin to generate POJO classes from JSON schema files.

For the code that will be handling the generated classes, it would be best if they could implement an interface to ensure that the available methods are present and avoid using reflection.

I know this is already possible by adding the 'javaInterfaces' in the jsonSchema, but in this particular case the schemas are defined by the user and we would like to hide this implementation detail.

For general purpose this should likely be a map of interface -> classes that should implement it, but for our specific use case we just need the same interface to be applied to all generated classes, so it could be a defaultJavaInterfaces or something like that.

I think this would be a simple change if it is something that you want to support. In the EnumRule and ObjectRule where we currently have

if (node.has("javaInterfaces")) {
    addInterfaces(jclass, node.get("javaInterfaces"));
} 
(...)
private void addInterfaces(JDefinedClass jclass, JsonNode javaInterfaces) {
    for (JsonNode i : javaInterfaces) {
        jclass._implements(jclass.owner().ref(i.asText()));
    }
}

it could be changed to something like

List<String> defaultInterfaces = ruleFactory.getGenerationConfig().getDefaultJavaInterfaces();
Set<String> javaInterfaces = new HashSet<>(defaultInterfaces);
if (node.has("javaInterfaces")) {
    List<String> nodeInterfaces = node.get("javaInterfaces").stream().map(JsonNode::asText).collect(Collectors.toList()));
    javaInterfaces.addAll(nodeInterfaces);
} 
addInterfaces(jclass, javaInterfaces);

(...)
private void addInterfaces(JDefinedClass jclass, Set<String> javaInterfaces) {
    for (String javaInterface : javaInterfaces) {
        jclass._implements(jclass.owner().ref(javaInterface));
    }
}
@unkish
Copy link
Collaborator

unkish commented Jun 2, 2023

Hi

I'm afraid that given case/problem is too specific to your domain, thus implementing it might be against jsonschema2pojo "philosophy":

With jsonschema2pojo, we cannot attempt to support every possible preferred way of writing Java source code. Our intention is to create a correct approach that maps between JSON and Java and follows Java conventions. It is not the intention of this library to allow endless configurability to get the exact Java source code that you prefer, as that is too big a task and would create a system that is far harder to extend and maintain. See JAXB for a similar approach - the goal is to provide a correct implementation, not to allow generation of whatever source code style you prefer.


That being said it should be possible to achieve desired result by passing custom rule factory & custom rules.

@antssilva96
Copy link
Author

Hello! Yeah, that makes sense.

Could you elaborate on the custom rule factory and rules approach? Is there a way to do this without having to re-compile the plugin and using the new custom version ?

@unkish
Copy link
Collaborator

unkish commented Jun 2, 2023

I think that we could take https://github.com/itzg/jsonschema2pojo-rules-bettermaps as an example (maven approach).

Basically an "artifact" would have to be created/published.

It would need to contain a custom rule factory class similar to https://github.com/itzg/jsonschema2pojo-rules-bettermaps/blob/71392cafe1e439ac81c42f4c21dde8fa59b79cc1/src/main/java/me/itzg/jsonschema2pojo/bettermaps/BetterMapsRuleFactory.java#L16

You would also have to override/extend rules that are of interest eg. ObjectRule (note that this is just an example):

public class CustomObjectRule extends ObjectRule {

    protected CustomObjectRule(RuleFactory ruleFactory, ParcelableHelper parcelableHelper, ReflectionHelper reflectionHelper) {
        super(ruleFactory, parcelableHelper, reflectionHelper);
    }

    @Override
    public JType apply(String nodeName, JsonNode node, JsonNode parent, JPackage _package, Schema schema) {
        final JDefinedClass jClass = (JDefinedClass) super.apply(nodeName, node, parent, _package, schema);
        // add custom interface's
        jClass._implements(resolveType(jClass._package(), "org.jsonschema2pojo.integration.yaml.YamlTypeIT.InterfaceWithGenerics<String,Integer,Boolean>"));
        return jClass;
    }
}

Once custom rule factory artifact is compiled/published add it as a dependency of the plugin and set the customRuleFactory to point at it (see example in https://github.com/itzg/jsonschema2pojo-rules-bettermaps/blob/master/README.md)

@antssilva96
Copy link
Author

Thanks for the detailed answer!
We don't want to own/maintain our own version of the plugin for now, but maybe in the future we have to go that way.

I'll close this issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants