如何将java对象序列化为field.path = field.value

时间:2015-09-12 10:20:19

标签: java serialization reflection

我有以下模型类:

package com.ab.model;

import java.util.List;

public class Request {

    public Request(String requestType, Body body, List<String> emails) {
        this.requestType = requestType;
        this.body =body;
        this.emails = emails;
    }

    private String requestType;
    private Body body;
    private List<String> emails;

    public String getRequestType() {
        return requestType;
    }

    public void setRequestType(String requestType) {
        this.requestType = requestType;
    }

    public Body getBody() {
        return body;
    }

    public void setBody(Body body) {
        this.body = body;
    }

    public List<String> getEmails() {
        return emails;
    }

    public void setEmails(List<String> emails) {
        this.emails = emails;
    }

}

class Body {

    private String content;
    private List<Header> headers;

    public Body(String content, List<Header> headers) {
        this.content = content;
        this.headers = headers;
    }

    public String getContent() {
        return content;
    }
    public void setContent(String content) {
        this.content = content;
    }
    public List<Header> getHeaders() {
        return headers;
    }
    public void setHeaders(List<Header> headers) {
        this.headers = headers;
    }   

}

class Header {

    private String headerName;

    public Header (String headerName) {
        this.headerName = headerName;
    }

    public String getHeaderName() {
        return headerName;
    }

    public void setHeaderName(String headerName) {
        this.headerName = headerName;
    }

}

以下Request类的实例:

Request request = new Request(
                "get", 
                new Body("abcdefg", 
                        Arrays.asList(new Header("header_one"))), 
                Arrays.asList("a@a.com", "b@b.com"));

您是否知道可以将请求对象序列化为以下字符串的任何库或算法?

requestType = "get"
body.content = "abcdefg"
body.headers[0].headerName = "header_one"
emails[0] = "a@a.com"
emails[1] = "b@b.com"

我知道我可以将它序列化为json,xml等,但这些不适合我的用例。 基本上我需要一个序列化,如: field.nestedField.reallyNestedField =&#34;其原始值&#34;

下一步,我打算读取生成的字符串并为每个字段/ nestedField生成任意数据,然后使用来自Apache的PropertyUtils反序列化它,例如:

PropertyUtils.setProperty(requestObject, "requestType", "random type");
PropertyUtils.setProperty(requestObject, "body.content", "random content");
//...

非常感谢! 安德烈

2 个答案:

答案 0 :(得分:0)

如何覆盖toString()默认方法来读取和输出成员变量作为文本。您可以使用super来引用您的SuperClass及其成员。

PS:您的班级中没有默认构造函数!如果你有你的参数列表的构造函数,建议在你的类中包含你的无参数默认构造函数!特别是在您实现与序列化/反序列化相关的一些逻辑的情况下!

答案 1 :(得分:0)

您可以使用Commons PropertyUtils对类/对象属性进行迭代和递归。

根据实现的复杂程度,您可能需要对原始类型/包装类型/集合类型进行某种类型检查(以下内容使用Commons ClassUtils)。

public static List<String> getPropertyDescriptorPaths(Class<?> clazz) {
    return getPropertyDescriptorPaths("", clazz);
}

private static List<String> getPropertyDescriptorPaths(String prefix, Class<?> clazz) {
    List<String> paths = new ArrayList<>();

    PropertyDescriptor[] descriptors = PropertyUtils.getPropertyDescriptors(clazz);

    for (PropertyDescriptor pd : descriptors) {
        if (isSimpleType(pd.getPropertyType())) {
            paths.add(prefix + pd.getName());
        } else if (!pd.getName().equals("class")) {
            paths.addAll(getPropertyDescriptorPaths(pd.getName() + ".", pd.getPropertyType()));
        }
    }

    return paths;
}

private static boolean isSimpleType(Class<?> clazz) {
    return ClassUtils.isPrimitiveOrWrapper(clazz) || clazz.equals(String.class) || isCollectionOrArray(clazz);
}

private static boolean isCollectionOrArray(Class<?> clazz) {
    return isCollection(clazz) || clazz.isArray();
}

private static final List<Class<?>> COLLECTION_TYPES = Arrays.asList(new Class<?>[] { List.class, Map.class, Set.class });

private static boolean isCollection(Class<?> clazz) {
    for (Class<?> eachClass : COLLECTION_TYPES) {
        if (eachClass.isAssignableFrom(clazz)) {
            return true;
        }
    }
    return false;
}

将属性名称与class进行比较的条件是因为每个对象都有一个getClass()方法,我们对此并不在意。

将其与您的课程一起使用,我们得到的结果是:

System.out.println(getPropertyDescriptorPaths(Request.class));
// [emails, requestType, body.headers, body.content]