class ValueConverter implements Converter {

    @Override
    public void marshal(Object o, HierarchicalStreamWriter writer, MarshallingContext context) {

        ValueModel valueModel = ValueModel.acquire(o.getClass());

        valueModel.fields().forEach(fieldModel -> {

            if (fieldModel instanceof ArrayFieldModel) {
                try {

                    final Method indexedGet = fieldModel.getOrGetVolatile();
                    indexedGet.setAccessible(true);

                    writer.startNode(fieldModel.name());
                    for (int i = 0; i < ((ArrayFieldModel) fieldModel).array().length(); i++) {
                        writer.startNode(Integer.toString(i));
                        context.convertAnother(indexedGet.invoke(o, i));
                        writer.endNode();
                    }
                    writer.endNode();

                } catch (IllegalAccessException | InvocationTargetException e) {
                    throw new ConversionException("", e);
                }

                return;
            }

            try {

                final Method get = fieldModel.getOrGetVolatile();
                get.setAccessible(true);
                final Object value = get.invoke(o);

                writer.startNode(fieldModel.name());
                context.convertAnother(value);
                writer.endNode();

            } catch (Exception e) {
                Jvm.error().on(getClass(), "class=" + fieldModel.name(), e);
            }
        });

    }

    @Override
    public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) {<FILL_FUNCTION_BODY>}

    private void fillInObject(HierarchicalStreamReader reader, UnmarshallingContext context,
                              ValueModel valueModel, Object using) throws ClassNotFoundException {

        while (reader.hasMoreChildren()) {
            reader.moveDown();

            final String name = reader.getNodeName();

            FieldModel fieldModel =
                    valueModel.fields().filter(f -> f.name().equals(name)).findAny().orElseThrow(() -> new NoSuchElementException("No element with name " + name));

            if (fieldModel instanceof ArrayFieldModel) {

                while (reader.hasMoreChildren()) {

                    reader.moveDown();
                    try {
                        String index = reader.getNodeName();
                        int i = Integer.parseInt(index);
                        Method indexedSet = fieldModel.setOrSetOrderedOrSetVolatile();
                        indexedSet.setAccessible(true);
                        Class<?>[] parameterTypes = indexedSet.getParameterTypes();
                        Object value = context.convertAnother(null, parameterTypes[1]);
                        indexedSet.invoke(using, i, value);
                    } catch (Exception e) {
                        throw new ConversionException("", e);
                    }

                    reader.moveUp();
                }
                reader.moveUp();
                continue;
            }

            Method set = fieldModel.setOrSetOrderedOrSetVolatile();
            set.setAccessible(true);
            final Class<?>[] parameterTypes = set.getParameterTypes();
            final Object value = context.convertAnother(null, parameterTypes[0]);

            try {
                set.invoke(using, value);
            } catch (Exception e) {
                throw new ConversionException("", e);
            }

            reader.moveUp();
        }
    }

    @Override
    public boolean canConvert(Class clazz) {
        return Values.isValueInterfaceOrImplClass(clazz);
    }
}

        try {
            ValueModel valueModel = ValueModel.acquire(context.getRequiredType());
            Object result = valueModel.heapClass().newInstance();
            fillInObject(reader, context, valueModel, result);
            return result;
        } catch (Exception e) {
            throw new ConversionException(
                    "class=" + context.getRequiredType().getCanonicalName(), e);
        }
    
<no_super_class>