Generator for wrapper type (JsonNullable
)
#974
-
How do one implement a generator for a wrapper class like I'm trying to implement a wrapper type for https://github.com/OpenAPITools/jackson-databind-nullable, but I'm not sure if I'm on the right track. I guess need to implement a public class JsonNullablePocGenerator<T> extends AbstractGenerator<JsonNullable<T>> implements GeneratorSpec<JsonNullable<T>> {
public JsonNullablePocGenerator() {
this(Global.generatorContext());
}
public JsonNullablePocGenerator(final GeneratorContext context) {
super(context);
}
@Override
public String apiMethod() {
return "jsonNullable()";
}
@Override
protected JsonNullable<T> tryGenerateNonNull(final Random random) {
if (random.diceRoll(true)) {
return JsonNullable.undefined();
}
return null; // must be null to delegate creation to the engine
}
@Override
public Hints hints() {
return Hints.builder()
.afterGenerate(AfterGenerate.DO_NOT_MODIFY)
.with(InternalContainerHint.builder()
.generateEntries(1)
.createFunction(args -> args[0] == null
? JsonNullable.undefined()
: JsonNullable.of(args[0]))
.build())
.build();
}} Test public static void main(String[] args) {
var test = Instancio.of(Test.class)
.supply(all(JsonNullable.class), new JsonNullablePocGenerator<String>())
.create();
System.out.println(test.test); <---- always null
}
class Test {
JsonNullable<String> test;
}
|
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 2 replies
-
Solved it via a custom public final class InternalServiceProviderImpl implements InternalServiceProvider {
@Override
public InternalContainerFactoryProvider getContainerFactoryProvider() {
return new InternalContainerFactoryProviderImpl();
}
@Override
public InternalGetterMethodFieldResolver getGetterMethodFieldResolver() {
return new InternalGetterMethodFieldResolverImpl();
}
static final class InternalGetterMethodFieldResolverImpl implements InternalGetterMethodFieldResolver {
private static final String GET_PREFIX = "get";
private static final String IS_PREFIX = "is";
@Override
public Field resolveField(final Class<?> declaringClass, final String methodName) {
if (hasPrefix(GET_PREFIX, methodName)) {
final Field field = getFieldNameByRemovingPrefix(declaringClass, methodName, GET_PREFIX.length());
if (field != null) return field;
} else if (hasPrefix(IS_PREFIX, methodName)) {
final Field field = getFieldNameByRemovingPrefix(declaringClass, methodName, IS_PREFIX.length());
if (field != null) return field;
}
// class could be using property-style getters (e.g. java record)
return ReflectionUtils.getFieldOrNull(declaringClass, methodName);
}
@Nullable
private static Field getFieldNameByRemovingPrefix(
final Class<?> targetClass,
final String methodName,
final int getPrefixLength) {
final char[] ch = methodName.toCharArray();
ch[getPrefixLength] = Character.toLowerCase(ch[getPrefixLength]);
final String filedName = new String(ch, getPrefixLength, ch.length - getPrefixLength);
return ReflectionUtils.getFieldOrNull(targetClass, filedName);
}
private static boolean hasPrefix(final String prefix, final String methodName) {
return methodName.startsWith(prefix) && methodName.length() > prefix.length();
}
}
private static final class InternalContainerFactoryProviderImpl implements InternalContainerFactoryProvider {
@Override
@SuppressWarnings({"rawtypes", "unchecked"})
public <S, T> Function<S, T> getMappingFunction(
final Class<T> targetType,
final List<Class<?>> typeArguments) {
Function<?, ?> result = null;
if (targetType == EnumMap.class) {
result = (Function<Map<?, ?>, EnumMap<?, ?>>) other -> {
if (other.isEmpty()) {
return new EnumMap(typeArguments.iterator().next());
}
return new EnumMap(other);
};
}
return (Function<S, T>) result;
}
@Override
public boolean isContainer(final Class<?> type) {
return type == JsonNullable.class;
}
}
} |
Beta Was this translation helpful? Give feedback.
-
@NicklasWallgren could you provide an example of what you're trying to achieve in your test? Do you need to customise the value of the Without a custom generator, it should produce random values: @Test
void jsonNullable() {
class Pojo {
JsonNullable<String> value;
}
Pojo pojo = Instancio.create(Pojo.class);
// Sample output:
// JsonNullable[GKYZB]
// JsonNullable.undefined // if false generated for JsonNullable.isPresent
System.out.println(pojo.value);
} Might be relevant: |
Beta Was this translation helpful? Give feedback.
Solved it via a custom
InternalServiceProvider
. Is this the preferred way?