joelittlejohn / jsonschema2pojo

Generate Java types from JSON or JSON Schema and annotate those types for data-binding with Jackson, Gson, etc

Home Page:http://www.jsonschema2pojo.org

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

fixed missing enum support for JSONB1 styled output

joerg-d-schneider-db opened this issue · comments

I finally fixed the currently missing support to properly handle enums when generating JSONB1 standard output.
I managed to do that by implementing a customAnnotator and a customRuleFactory.
As my company does not permit to upload any files, I share that solution by posting here - it's not much code anyway.
Thx

package com.db.dice.rules;

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

import com.sun.codemodel.JClassContainer;
import com.sun.codemodel.JType;

/**
 * @author sf9100
 * @since Jun 2023
 */
public class EnumMapperRuleFactory extends RuleFactory {
	public EnumMapperRuleFactory(GenerationConfig generationConfig, Annotator annotator, SchemaStore schemaStore) {
		super(generationConfig, annotator, schemaStore);
	}

	public EnumMapperRuleFactory() {
		super();
	}

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

package com.db.dice.rules;

import javax.json.bind.adapter.JsonbAdapter;

import org.jsonschema2pojo.AnnotationStyle;
import org.jsonschema2pojo.model.EnumDefinition;
import org.jsonschema2pojo.rules.EnumRule;
import org.jsonschema2pojo.rules.RuleFactory;

import com.sun.codemodel.JDefinedClass;
import com.sun.codemodel.JMethod;
import com.sun.codemodel.JMod;

public class EnumMapperRule extends EnumRule {

	private final RuleFactory ruleFactory;
	public static final String SUFFIX = "Mapper";

	protected EnumMapperRule(RuleFactory ruleFactory) {
		super(ruleFactory);
		this.ruleFactory = ruleFactory;
	}

	@Override
	protected void applyCustomizations(EnumDefinition enumDefinition, JDefinedClass _enum) {
		if (this.ruleFactory.getGenerationConfig().getAnnotationStyle().equals(AnnotationStyle.JSONB1)
				|| this.ruleFactory.getGenerationConfig().getAnnotationStyle().equals(AnnotationStyle.JSONB1)) {
			
			try {
				// create an public static inner class inside the enum
				JDefinedClass c = _enum._class(JMod.PUBLIC | JMod.STATIC,
						enumDefinition.getNodeName() + EnumMapperRule.SUFFIX);
				

				if (c != null) {
					// implement the JsonbAdapter interface
				    c._implements(_enum.owner().ref(JsonbAdapter.class).narrow(_enum).narrow(String.class));
				    
					// create the adaptToJson method
					JMethod to = c.method(JMod.PUBLIC, String.class, "adaptToJson");
					to.annotate(Override.class);
					to.param(_enum, "obj");
					to.body().directStatement("return obj.value();");

					// create the adaptFromJson method
					JMethod from = c.method(JMod.PUBLIC, _enum, "adaptFromJson");
					from.annotate(Override.class);
					from.param(String.class, "obj");
					from.body().directStatement("return " + enumDefinition.getNodeName() + ".fromValue(obj);");
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		}

	}

}

package com.db.dice.util;

import javax.json.bind.annotation.JsonbTypeAdapter;

import org.jsonschema2pojo.AbstractAnnotator;

import com.db.dice.rules.EnumMapperRule;
import com.fasterxml.jackson.databind.JsonNode;
import com.sun.codemodel.JClass;
import com.sun.codemodel.JDefinedClass;
import com.sun.codemodel.JFieldVar;
import com.sun.codemodel.JType;

public class EnumJsonbAdapterAnnotator extends AbstractAnnotator {
	@Override
	public void propertyField(JFieldVar field, JDefinedClass clazz, String propertyName, JsonNode propertyNode) {
		super.propertyField(field, clazz, propertyName, propertyNode);
		if (propertyNode.has("enum")) {

			try {
				JClass temp1 = clazz.owner()
						.directClass(field.type().fullName() + "." + field.type().name() + EnumMapperRule.SUFFIX);
				
				field.annotate(JsonbTypeAdapter.class).param("value", (JType) temp1);

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