修剪复杂对象中的所有字符串元素

时间:2012-02-08 07:55:32

标签: java

我可以编写一个通用方法来修剪复杂对象(包含其他对象的对象)中的所有字符串吗?应该用java反射api来实现这个吗?谢谢。

我在下面提供了一个示例。但实际上,对象中可能存在多个对象。每个对象可能包含一个String集合或其他可能包含String的对象的集合。有没有办法修剪字符串 - 直接使用对象和集合中的字符串。

public class School{
   private List<Course> courses;
   private List<Student> students;       
   // Getters and Setters
}

public class Course{
   private String name;
   private String xxx;
   private String yyy;
   private List<String> zzzList;
}

public class Student{
   private Map<String,String> xxx;
   private List<Course> courseList;
}

6 个答案:

答案 0 :(得分:6)

是的,反思就是这样。基本上,你需要:

  • 获取顶级对象的类(使用[object] .getClass())

  • 获取对象的所有字段(使用clazz.getFields() - 注意,它只适用于公共字段)

  • 检查字段是否为String(获取field.getType()并检查它是否为字符串,或者执行field.get(对象)和instanceof String)

  • 如果是这种情况,请使用field.set([您的对象],[修剪后的字符串])

  • 将对象中的字符串替换为剪裁后的字符串
  • 如果字段是对象但不是字符串,则以递归方式调用方法

这样就可以了。

----刚看到你的更新

修剪集合中的字符串会比较棘手,因为字符串不会作为集合的公共字段公开(例如List)。

你需要一些更聪明的东西,它会检查一个对象是否是List,Map或其他......的实例(或派生类!)。 主要问题是java泛型是在编译类型下使用擦除类型完成的。所以你不能知道你的字段是List [String]或List [Integer]或者其他什么。每个列表[?]都成为列表。

你仍然可以尝试这样做:

  • 如果字段类型为List
  • 遍历列表值
  • 如果值为instanceof String,则必须将其从列表中删除并插入修剪后的版本
  • 如果某个值是一个对象,那么您可以使用您的方法再次递归。

在现实生活中的样本不是很有趣,但在图书馆方面可能更多。 很长的路要走!

答案 1 :(得分:2)

是的,你可以很容易地用反射做到这一点。只需检查字段是否为instanceof String

确切的方法取决于您的对象结构。

答案 2 :(得分:1)

/*********************************************************************************************
 * Trim first level children of string type in this object
 * @param obj which all string properties to be trimmed
 *********************************************************************************************/
public static void trimAll(final Object obj)
throws LocalException
{
    if (obj==null) return;

    final Class    c           = obj.getClass();
    final Method[] methods     = c.getMethods();
    final Class[]  SETTER_ARGS = new Class[]{String.class};
    final Object[] SETTER_VAL  = new Object[1];
    final String   SET         = "set";
    final String   GET         = "get";
    final String   SPACE       = "\u0020";
    final String   TAB         = "\t";

    for (final Method m:methods)
    {
        try
        {
            final String name=m.getName();
            if (
                name.length()>GET.length()
             && name.indexOf(GET)==0
             && m.getReturnType().equals(String.class)
             && m.getParameterTypes().length==0)
            {
                final String v = (String)m.invoke(obj);
                if (v!=null && (v.contains(SPACE) || v.contains(TAB)) )
                {
                    final Method setter=c.getMethod(SET+name.substring(3),SETTER_ARGS);
                    if (setter!=null)
                    {
                        SETTER_VAL[0]=v.trim();
                        setter.invoke(obj,SETTER_VAL);
                    }
                }
            }
        }
        catch (final Throwable e)
        {
            throw new LocalException(LocalException.EC_GENERAL_EXCEPTION,e);
        }
    }
}

答案 3 :(得分:1)

我们还可以使用Jackson进行序列化,然后反序列化对象。反序列化时,我们可以使用自定义反序列化器修剪所有String值。

创建这样的反序列化器:

public class TrimStringToNullDeserializer extends JsonDeserializer<String> {

@Override
public String deserialize(JsonParser jsonParser, DeserializationContext deserializationContext)
        throws IOException {
    String value = jsonParser.getValueAsString();

    if (isNull(value)) {
        return null;
    }
    value = value.trim();
    if (value.length() == 0) {
        value = null;
    }
    return value;
}

然后我们可以使用Jackson修剪所有值:

public class TrimStringToNullConfiguration {

private ObjectMapper objectMapper;

public Client trimToNull(Client inputClient) throws JsonProcessingException {
    return getObjectMapper().readValue(getObjectMapper().writeValueAsString(inputClient), Client.class);
}

private ObjectMapper getObjectMapper() {
    if (isNull(objectMapper)) {
        objectMapper = new ObjectMapper();
        SimpleModule module = new SimpleModule();
        module.addDeserializer(String.class, new TrimStringToNullDeserializer());
        objectMapper.registerModule(module);
    }
    return objectMapper;
}

我已经提供了一个有效的示例over here.

答案 4 :(得分:0)

private <T> T  toTrim(T t) {
    Field[] fields = t.getClass().getFields();
    for (Field field : fields) {
        try {
            if (field.get(t) instanceof String) {
                Object o = field.get(t);
                String s = (String) o;
                field.set(t, s.trim().toUpperCase());
            }
        } catch (IllegalAccessException e) {
            log.info("Error converting field "+ field.getName() );
        }
    }
    return t;
}

答案 5 :(得分:-1)

if (yourObject instanceof String){
    yourObject = yourObject.trim();
}

希望有所帮助:)