@Override
    public <T> T clone(T object) {
        if (object instanceof String) {
            return object;
        } else if (object instanceof Collection) {
            Object firstElement = findFirstNonNullElement((Collection) object);
            if (firstElement != null && !(firstElement instanceof Serializable)) {
                JavaType type = TypeFactory.defaultInstance().constructParametricType(object.getClass(), firstElement.getClass());
                return objectMapperWrapper.fromBytes(objectMapperWrapper.toBytes(object), type);
            }
        } else if (object instanceof Map) {
            Map.Entry firstEntry = this.findFirstNonNullEntry((Map) object);
            if (firstEntry != null) {
                Object key = firstEntry.getKey();
                Object value = firstEntry.getValue();
                if (!(key instanceof Serializable) || !(value instanceof Serializable)) {
                    JavaType type = TypeFactory.defaultInstance().constructParametricType(object.getClass(), key.getClass(), value.getClass());
                    return (T) objectMapperWrapper.fromBytes(objectMapperWrapper.toBytes(object), type);
                }
            }
        } else if (object instanceof JsonNode) {
            return (T) ((JsonNode) object).deepCopy();
        }

        if (object instanceof Serializable) {
            try {
                return (T) SerializationHelper.clone((Serializable) object);
            } catch (SerializationException e) {
                //it is possible that object itself implements java.io.Serializable, but underlying structure does not
                //in this case we switch to the other JSON marshaling strategy which doesn't use the Java serialization
            }
        }

        return jsonClone(object);
    }
@Test
    public void should_clone_serializable_complex_object_with_serializable_nested_object() {
        Map<String, List<SerializableObject>> map = new LinkedHashMap<>();
        map.put("key1", Lists.newArrayList(new SerializableObject("name1")));
        map.put("key2", Lists.newArrayList(
            new SerializableObject("name2"),
            new SerializableObject("name3")
        ));
        Object original = new SerializableComplexObject(map);
        Object cloned = serializer.clone(original);
        assertEquals(original, cloned);
        assertNotSame(original, cloned);
    }