public static Object value(String strValue, Field field) {
        requireNonNull(field);
        // if field is not primitive type
        Type fieldType = field.getGenericType();
        if (fieldType instanceof ParameterizedType) {
            Class<?> clazz = (Class<?>) ((ParameterizedType) field.getGenericType()).getActualTypeArguments()[0];
            if (field.getType().equals(List.class)) {
                // convert to list
                return stringToList(strValue, clazz);
            } else if (field.getType().equals(Set.class)) {
                // covert to set
                return stringToSet(strValue, clazz);
            } else if (field.getType().equals(Map.class)) {
                Class<?> valueClass =
                    (Class<?>) ((ParameterizedType) field.getGenericType()).getActualTypeArguments()[1];
                return stringToMap(strValue, clazz, valueClass);
            } else if (field.getType().equals(Optional.class)) {
                Type typeClazz = ((ParameterizedType) fieldType).getActualTypeArguments()[0];
                if (typeClazz instanceof ParameterizedType) {
                    throw new IllegalArgumentException(format("unsupported non-primitive Optional<%s> for %s",
                            typeClazz.getClass(), field.getName()));
                }
                return Optional.ofNullable(convert(strValue, (Class) typeClazz));
            } else {
                throw new IllegalArgumentException(
                        format("unsupported field-type %s for %s", field.getType(), field.getName()));
            }
        } else {
            return convert(strValue, field.getType());
        }
    }
@Test
    public void testNullStrValue() throws Exception {
        class TestMap {
            public List<String> list;
            public Set<String> set;
            public Map<String, String> map;
            public Optional<String> optional;
        }

        Field listField = TestMap.class.getField("list");
        Object listValue = FieldParser.value(null, listField);
        assertNull(listValue);

        listValue = FieldParser.value("null", listField);
        assertTrue(listValue instanceof List);
        assertEquals(((List) listValue).size(), 1);
        assertEquals(((List) listValue).get(0), "null");


        Field setField = TestMap.class.getField("set");
        Object setValue = FieldParser.value(null, setField);
        assertNull(setValue);

        setValue = FieldParser.value("null", setField);
        assertTrue(setValue instanceof Set);
        assertEquals(((Set) setValue).size(), 1);
        assertEquals(((Set) setValue).iterator().next(), "null");

        Field mapField = TestMap.class.getField("map");
        Object mapValue = FieldParser.value(null, mapField);
        assertNull(mapValue);

        try {
            FieldParser.value("null", mapField);
        } catch (IllegalArgumentException iae) {
            assertTrue(iae.getMessage().contains("null map-value is not in correct format key1=value,key2=value2"));
        }

        Field optionalField = TestMap.class.getField("optional");
        Object optionalValue = FieldParser.value(null, optionalField);
        assertEquals(optionalValue, Optional.empty());
    }