开发者

Reverse ToStringBuilder : convert string to object

开发者 https://www.devze.com 2023-01-28 08:49 出处:网络
Is there a way to convert my output from ToStringBuilder back to java object? I am looking for an easy way to represent a Java object in readable text file and being able to convert开发者_运维技巧 b

Is there a way to convert my output from ToStringBuilder back to java object?

I am looking for an easy way to represent a Java object in readable text file and being able to convert开发者_运维技巧 back and forth between string and object.

Thanks,


You must define a strict format and follow it with a parser. There are two accepted formats:

  • XML - you can use java.beans.XMLEncoder
  • JSON - use Jackson or gson

If you don't choose these formats you will have to handle the parsing yourself.

The ToStringBuilder does not seem to have a reverse equivalent. Furthermore it is wrong to use this string representation for such purposes - it is meant only for debug.


You'll have to parse your string representation of the object and then construct a new object initialised with those values.

If you want to keep it generic and have it work for any object type, you can use Apache BeanUtils to help.

For example, if your string representation is:

Person@7f54[name=Stephen,age=29,smoker=false]

Parse out the class name, fields and values. Then use BeanUtils to construct a new Person:

String className = "Person";
Class beanClass = Class.forName(className);
Person myPerson = (Person)beanClass.newInstance();
BeanUtils.setProperty(myPerson, "name", "Stephen");
BeanUtils.setProperty(myPerson, "age", "29");
BeanUtils.setProperty(myPerson, "smoker", "false");

This assumes that your Person class is a bean and exposes getters/setters for its fields.


Sean, I came across your question while looking for a simple test case converter based on a reflection-based String output of an object. While a more robust library for json or XML is certainly important for a wide range of input, this is handy for quick and dirty test cases. It handles simple, non-nested POJOs. Its only dependency is apache commons.

I'm using this toString format:

@Override
public String toString() {
    return ReflectionToStringBuilder.toString(this, ToStringStyle.SHORT_PREFIX_STYLE);
}

Here is the class:

public class FromStringBuilder {

/**
 * Parses a string formatted with toStringBuilder
 * 
 * @param input - ex. "Path[id=1039916,displayName=School Home,description=<null>,...]"
 * @return hashmap of name value pairs - ex. id=1039916,... 
 */
public static Map<String, String> stringToMap(String input) {
    LinkedHashMap<String, String> ret = new LinkedHashMap<String, String>();
    String partsString = StringUtils.substringBetween(input, "[", "]");
    String[] parts = partsString.split(",");
    for (String part:parts) {
        String[] nv = part.split("=");
        if (!StringUtils.equals("<null>", nv[1])) {
            ret.put(nv[0], nv[1]);
        }
    }
    return ret;
}

public static <T> T stringToObject(String input, Class<T> clazz) throws IllegalAccessException, InvocationTargetException, InstantiationException {
    Map<String, String> map = stringToMap(input);
    T ret = clazz.newInstance();
    BeanUtils.copyProperties(ret, map);
    return ret;
}
}


XStream library is the perfect one


Here is an example of using Gson:

public class GsonTest {
    static class Name { String first; String last; }
    static class Data { int number; Name name = new Name(); }

    public static void main(String[] args) {
        Gson gson = new Gson();

        Data data1 = new Data();
        data1.number = 1;
        data1.name.first = "Joe";
        data1.name.last = "Smith";
        print("data1", data1);

        String jsonString = gson.toJson(data1);
        System.out.println("jsonString: " + jsonString);

        Data data2 = gson.fromJson(jsonString, Data.class);
        print("data2", data2);
    }

    private static void print(String id, Data data) {
        System.out.println(id + "     :" 
                + " number=" + data.number 
                + " name.first=" + data.name.first
                + " name.last=" + data.name.last);
    }
}

Output

data1     : number=1 name.first=Joe name.last=Smith
jsonString: {"number":1,"name":{"first":"Joe","last":"Smith"}}
data2     : number=1 name.first=Joe name.last=Smith

Speed

Gson should be roughly as fast as any other comparable reflection-based Object<->Text serialization framework, but I do not have benchmark data.

Bean Support

Unlike XStream(optionally) and java.beans.XMLEncoder/XMLEncoder, Gson does not use a class's setter and getter methods. Rather it reads and writes the member fields of the class directly, similar to Java binary serialization (ObjectOutputStream, etc.) While Gson should be able to properly marshal and unmarshal most JavaBeans, this implementation detail of Gson must be kept in mind and accounted for.

Pretty-printed JSON Output

By default GSON outputs JSON all on one line, as an optimization. It can output JSON that is slightly easier to read. Do this by constructing the Gson object in a slightly different way:

Gson gson = new GsonBuilder().setPrettyPrinting().create();

The JSON output (continuing the example above), now looks like:

{
  "number": 1,
  "name": {
    "first": "Joe",
    "last": "Smith"
  }
}

instead of

{"number":1,"name":{"first":"Joe","last":"Smith"}}
0

精彩评论

暂无评论...
验证码 换一张
取 消