- Casting Class into String and vice versa in Java
- 8 Answers 8
- How to parse a Field object to a String (Java)
- 1 Answer 1
- java toString for any object [duplicate]
- 8 Answers 8
- Serialize the whole class as a String field instead of a JSON Object
- 1 Answer 1
- UPDATE: Without using Jackson (no third party dependencies)
Casting Class into String and vice versa in Java
I have a program in which I need to store a Class object into memory by casting it into String. Is it possible to convert the String back into the original Class so that I can use that class variables? I am doing this in JAVA. Example: test.java
class hello < public String h1; public String h2; >public class test < public static void main(String[] args) < hello h = new hello(); h.h1 = "hello"; h.h2 = "world"; String s = h.toString(); System.out.println("Print s : "+s); // Now I need to convert String s into type hello so that // I can do this: // (hello)s.h1; // (hello)s.h2; >>
NOTE: this is not a homework, this is a personal project and I would be grateful if anyone can help! Thanks! Ivar
You are not «casting» the object to a String, you’re calling a method (toString()) that returns a String description of the object (typically intended for debugging/logging). This is not a reversible operation — look into serialization as suggested by Derek.
Please clarify: «need to store . into memory»? Do you mean to need to persist it / save it somewhere like a disk file or a database?
yes, i want to persist an object as string into voldemort. i managed to do it using serialization and de-serialization. thank you so much! — ravi
8 Answers 8
toString() is not the same thing as Serialization. That is merely a description of the Class; listing some values of that particular instance of the Class etc.
I think what you want to do is Serialization. I’m confused by your comment:
// Now I need to convert String s into type hello so that // I can do this: // (hello)s.h1; // (hello)s.h2;
You can’t just cast String objects to arbitrary class types. Maybe you can elaborate on what you’re trying to accomplish here. If you want to be able to «save» a class to a file, then read it back in as an object, you want Serialization. Like this:
import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; class Hello implements Serializable < public String h1; public String h2; @Override public String toString() < return "< h1: " + h1 + ", h2: " + h2 + " >"; > public static void main(String[] args) throws Exception < Hello h = new Hello(); h.h1 = "hello"; h.h2 = "world"; ObjectOutputStream outstream = new ObjectOutputStream(new FileOutputStream("hello.ser")); outstream.writeObject(h); System.out.println("1) h: " + h); h = null; System.out.println("2) h: " + h); ObjectInputStream instream = new ObjectInputStream(new FileInputStream("hello.ser")); h = (Hello) instream.readObject(); System.out.println("3) h: " + h); >>
It can get more complicated when your fields are more complex classes than String. Implementing Serializable is just a «marker» interface that says that the object can be serialized, it doesn’t require any methods to be implemented. Your simple class just needs to be written out using an ObjectOutputStream and can be read back in using an ObjectInputStream.
How to parse a Field object to a String (Java)
I have a Field object Field f and know that it is an instance of String . How do I actually parse this Field f to a String s ? I tried to set the value of the field (this doesn’t work). My Code:
Field[] fields=LanguageHandler.class.getDeclaredFields(); for(Field field:fields) < if(field.getType().equals(String.class))< field.setAccessible(true); try < field.set(handler, ChatColor.translateAlternateColorCodes('&', cfg.getString(field.getName()))); >catch (IllegalArgumentException | IllegalAccessException e) < // TODO Auto-generated catch block e.printStackTrace(); >> >
1 Answer 1
A field is never an instance of a String. It’s a field. What you probably think is, that the Field stores a String. And you do not parse fields, you can only access them. A field belongs to a class, and thus, to get/set it, you must give the actual object where you want to get the value from (or set it to) as a parameter (except for static fields, see below).
A field can either be static or not. For example.
If it is static, then you do not need an object to access it and would call.
field.setAccessible(true); // to allow accessing it if private, etc. String s = (String)field.get(null);
If the field is not static, then you need an object in which the field has some value, for example something like this.
Something mySomething = new Something(); something.setMyOtherField( "xyz" );
. and you would end up calling.
field.setAccessible(true); // to allow accessing it if private, etc. String s = (String)field.get( something ); // s == "xyz"
java toString for any object [duplicate]
I have a lot of data objects, and I want to be able to generate a String representing each object, without implementing a toString method for each one. I’m thinking of reflection for getting the fields and its values. any other ideas? thanks.
i just need the fields and the values but i have maybe 50 objects and i dont want to implement toString for each one of them.
There is a default toString() method for each object ;). It might help if your question explains why you’re not happy with that one!
@ivy, the default toString() method is the one in Object, which is essentially useless. OP has said he wants to see fields and values.
8 Answers 8
You are welcome to use ToStringBuilder from jakarta. It has 2 modes one requires adding all fields you need using API, other is reflection based:
@Override public String toString()
I used it several years ago. Do not remember exactly but it is not too complicated. Read javadoc — I am sure you will succeed.
Use the JUtils plugin to generate the toString method at package level
Or using reflection you could try something like this:
public static void toString(Object object) throws InvocationTargetException, IllegalArgumentException, IllegalAccessException < Class c = object.getClass(); Method[] methods = c.getMethods(); for (Method method : methods) < if(method.getName().startsWith("get"))< System.out.println(method.getName()+" ->" +method.invoke(object, null)); > > >
The JUtil plugin would be best because that will allow you to change the toString of a object later on if you need provide more information about the object.
If you hava a lot of objects then instead of adding toString in every class use code instrumentation (you can alter .class in jars or change them at loadtime using javaagent). For example AspectJ would help, but there are lots other alternatives. For example you can do such a thing (using AspectJ and ToStringBuilder from Apache Commons):
@Aspect public class ToStringAspect < @Around("execution(String *.toString()) && target(t) && within(your.target.package.*)") public String toStringCall(Object t) < return ToStringBuilder.reflectionToString(t); >>
ToStringBuilder is very flexible. e.g. if you don’t need class name use style by setting StandardToStringStyle#setUseClassName(false):
public String toStringCall(Object t)
There are few ways to implement toString method.
- Reflections (Apache library)
@Override public String toString()
// GSON library for JSON @Override public String toString() < return new com.google.gson.Gson().toJson(this); >// Jackson libabry for JSON/YAML @Override public String toString() < try < return new com.fasterxml.jackson.databind.ObjectMapper().writerWithDefaultPrettyPrinter().writeValueAsString(this); >catch (com.fasterxml.jackson.core.JsonProcessingException e) < e.printStackTrace(); >return null; >
@Override public String toString()
@Override public String toString()
The toString method is inherited by every Class in Java, from java.lang.Object . I don’t see how you can avoid not implementing (actually overriding) Object.toString . Also, methods are defined for each class, and not for each object.
You could use a inheritance hierarchy to solve this, by having your classes inherit from a common class that overrides the default toString implementation. This implementation may use reflection to reflect on the fields of the class (not the parent class, but actually the class for the current object), and generate the string.
You can also investigate the use of bytecode weaving if you do not want to override the method at all. Personally, I do not think that the effort invested in bytecode weaving is not worth it, especially when you could have overridden toString .
Serialize the whole class as a String field instead of a JSON Object
I have an object that uses a class instance as a wrapper for the String type. How would I serialize my class into a JSON object using JAX-RS and Java EE 6 by using only the toString() method without creating a JSON object for the class and each fields? Class to be serialized:
public class Text < private String content; protected Text( String content ) < this.content = content; >public static Text from( String content ) < return new Text( "The text content"); >// This is a method that is used by the subclass and has no meaning for serialization protected String getContent() < return content; >// This should be used to serialize this class into a String, instead of an object @Override public String toString() < return content; >>
public class EditorStoryChapterInput < private Text title; public Text getTitle() < return title; >>
Result expected: I want to serialize as < "title": "The text content" >instead of < "title": < content: "the text content" >> . EDIT: Looking in the Jackson FAQ I found something useful, and what I want is probably the equivalent of what I found, but inside a JAX-RS/Java EE 6 environment in JBoss EAP 6.1. There is nothing as @JsonValue in my classpath using JBoss EAP 6.1: http://wiki.fasterxml.com/JacksonFAQ#Serializing_values_as_simple_types
JBoss will already have a Jackson provider built in. But you still need the Jackson dependency in your project, in order to compile using the Jackson annotations. So if you are using Maven, you can just grab the dependency and give it a provided scope.
Is there a spec compliant way to serialize it in the way I want to? It seems a pretty common use case.
I don’t know about spec compliant, but I just tested it, adding the Jackson dependency to my project, and just putting the @JsonValue over the toString() link mentioned in the link, and it works fine. Like I said, JBoss is using Jackson under the hood to do the serializing. So there’s nothing wrong with using it in your project. You just need to add the dependency in order to compile the annotation. You can get it straight from the server modules if you need to do. But it’ll be easier to just use Maven
1 Answer 1
From Comments:
I don’t know about spec compliant, but I just tested it, adding the Jackson dependency to my project, and just putting the @JsonValue over the toString() like mentioned in the link, and it works fine. Like I said, JBoss is using Jackson under the hood to do the serializing. So there’s nothing wrong with using it in your project. You just need to add the dependency in order to compile the annotation. You can get it straight from the server modules if you need to do. But it’ll be easier to just use Maven
Here are the classes I used for the example. I’ll post the classes, then I point out how to get the dependencies.
/** Getter and Setters added for Jackson discovery **/ public class Text < private String content; public void setContent(String content) < this.content = content; >protected String getContent() < return content; >@Override @JsonValue public String toString() < return content; >>
Your EditorStoryChapterInput class
public class EditorStoryChapterInput < private Text title; public void setTitle(Text title) < this.title = title; >public Text getTitle() < return title; >>
@Path("/json") public class JsonResource < @GET @Produces(MediaType.APPLICATION_JSON) public Response getJson() < EditorStoryChapterInput input = new EditorStoryChapterInput(); Text title = new Text(); title.setContent("Hello World"); input.setTitle(title); return Response.ok(input).build(); >>
The Application class to register out resource
@ApplicationPath("/rest") public class JsonApplication extends Application < @Override public Set> getClasses() < Set> classes = new HashSet>(); classes.add(JsonResource.class); return classes; > >
Get the Dependencies
If you are using Maven, you just need the jackson-core-asl artifact. When I use JBoss, I prefer to use their boms, so they can manage the versions. So What your pom would look something like (Remember I said we can use provide scope, because JBoss already has these dependencies. We just need it to compile)
org.jboss.bom jboss-javaee-6.0-with-resteasy 1.0.7.Final pom import org.codehaus.jackson jackson-core-asl provided . Other dependencies
If you’re not using Maven, you can simply look inside
There you will find the jackson-core-asl-1.9.9.redhat-3.jar . Just add that to your project however you normally add jars to your project. Tested this approach, with same result
Let me know if you have any problems adding the dependency.
UPDATE: Without using Jackson (no third party dependencies)
We can use the Java API for JSON Processing, and implement our own MessageBodyWriter , which will be used from writing the EditorStoryChapterInput object to the response OutputStream . It might look something like
@Provider @Produces(MediaType.APPLICATION_JSON) public class TextMessageBodyWriter implements MessageBodyWriter < @Override public boolean isWriteable(Class type, Type type1, Annotation[] antns, MediaType mt) < return type == EditorStoryChapterInput.class; >@Override public long getSize(EditorStoryChapterInput t, Class type, Type type1, Annotation[] antns, MediaType mt) < return -1; >@Override public void writeTo(EditorStoryChapterInput input, Class type, Type type1, Annotation[] antns, MediaType mt, MultivaluedMap mm, OutputStream out) throws IOException, WebApplicationException < Text title = input.getTitle(); JsonObject jsonObject = Json.createObjectBuilder() .add("title", title.toString()).build(); try (JsonWriter jsonWriter = Json.createWriter(out)) < jsonWriter.writeObject(jsonObject); >> >
When searching for MessageBodyWriters , JAX-RS will look at the @Produces annotation to see what type it produces, and if it matches the @Produces method on our resource method, the writer will be put into a list for the framework to traverse. Next it will check the isWritable method on each of the writers. If it returns true, then that’s the writer it will use. In our case, we return true if the return type of the response body is of EditorStoryChapterInput type.
In the writeTo method, we use the Java JSON Processing API to create a JsonObject and write it to the OutputStream provided to us by the framework.
Then we can register the writer with the application
@ApplicationPath("/rest") public class TextApplication extends Application < @Override public Set> getClasses() < final Set> classes = new HashSet<>(); classes.add(JsonResource.class); classes.add(TextMessageBodyWriter.class); return classes; > >
Testing it with the same JsonResource class from above, we get the output