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"}}
Related
I have a for loop which iterates and generates key value pairs for different employees.
I need to create a JSON array like below and write it to a JSON file at the end.
I am having trouble figuring out the ideal way to code it (JSON Objects -> JSON Array -> JSON file?).
I am open to use json-simple/GSON.
Desired JSON file format:
[
{
"employeeFirstName": "Mark",
"employeeLastName": "Williams",
"employeeDepartment": "Sales",
},
{
"employeeFirstName": "John",
"employeeLastName": "Carpenter",
"employeeDepartment": "Accounts",
},
{
"employeeFirstName": "David",
"employeeLastName": "Hunter",
"employeeDepartment": "Marketing",
},
]
I tried using a JSONObject and add it to a JSONArray. But, couldn't figure how to code it for iterations.
My current Java class:
public class Test {
public void createEmployeesJSONArrayFile(ITestContext iTestContext) {
for (ITestResult testResult : iTestContext.getFailedTests().getAllResults()) {
System.out.println("employeeFirstName: " + testResult.getEmployeeFirstName()));
System.out.println("employeeLastName: " + testResult.getEmployeeLastName());
System.out.println("employeeDepartment: " + testResult.getEmployeeDepartment());
}
}
}
What is the simplest or ideal way to achieve this?
A simple way to achieve this would be to use Gson, an API provided by Google. You could write the Collection of ITestResult objects to a file. The toJson function will take the Collection of ITestResult objects and write them to the the given Appenable object, which in this case is a BufferedWriter which points to a file.
(untested, one sec, not at workstation)
Collection<ITestResult> results = iTestContext.getFailedTests().getAllResults();
new GsonBuilder()
.create()
.toJson(results, Files.newBufferedWriter(Paths.get("path", "to", "file")));
If your goal is to write to file eventually, you can also use jackson apis.
ObjectMapper mapper = new ObjectMapper();
//To add indentation to output json
mapper.enable(SerializationFeature.INDENT_OUTPUT);
Collection<ITestResult> results = iTestContext.getFailedTests().getAllResults();
try{
mapper.writeValue(new File("/somepath/output.json"), results);
catch (IOException){
e.printStackTrace();
}
Note: Recommended to use single instance of object mapper
For following snippet:
public static final class Node {
class Employee {
private final String employeeFirstName;
private final String employeeLastName;
private final String employeeDepartment;
public Employee(String employeeFirstName, String employeeLastName, String employeeDepartment) {
this.employeeFirstName = employeeFirstName;
this.employeeLastName = employeeLastName;
this.employeeDepartment = employeeDepartment;
}
}
List<Employee> employees = Arrays.asList(
new Employee("Mark", "Williams", "Sales"),
new Employee("John", "Carpenter", "Accounts"),
new Employee("David", "Hunter", "Marketing"));
// String json = ...
}
Using gson-utils
String json = GsonUtils.writeValue(data);
Using jackson-utils
String json = JacksonUtils.writeValue(data);
This question already has an answer here:
json object convert to string java
(1 answer)
Closed 2 years ago.
Hi Guys I'm new to programming.
In my java code i have string like this.
String json ="{"name":"yashav"}";
Please help me out to print the values using pre-build java functions.
Expected output should be like below
name=yashav
First of all its not JSON.
If you want to work for actual JSON. There are many libraries which help you to transfer string to object.
GSON is one of those libraries. Use this to covert object then you can use keys to get values. Or you can iterate whole HashMap as per your requirements.
https://github.com/google/gson
{name:yashav} this is not a valid JSON format.
If you have {"name": "yashav"} you can use Jackson to parse JSON to java object.
class Person {
String name;
...
}
ObjectMapper mapper = new ObjectMapper();
Person person = mapper.readValue("{\"name\" : \"mkyong\"}", Person.class);
Forst of all, given String is NOT a json. It should be "{\"name\":\"yashav\"}". If you have a correct json string, you can use JacksonUtils.
Define a model:
class Url {
private String name;
public String getName() {
return name;
}
}
And parse the json string:
String json = "{\"name\":\"yashav\"}";
Url url = JsonUtils.readValue(json, Url.class);
System.out.format("name = %s", url.getName());
Another way is to use Regular Expression:
public static void main(String... args) {
String url = "{name:yashav}";
Pattern pattern = Pattern.compile("\\{(?<key>[^:]+):(?<value>[^\\}]+)\\}");
Matcher matcher = pattern.matcher(url);
if (matcher.matches())
System.out.format("%s = %s\n", matcher.group("key"), matcher.group("value"));
}
And finally, you can use plain old String operations:
public static void main(String... args) {
String url = "{name:yashav}";
int colon = url.indexOf(':');
String key = url.substring(1, colon);
String value = url.substring(colon + 1, url.length() - 1);
System.out.format("%s = %s\n", key, value);
}
I'm trying to parse the following body:
event=invoice.created&data%5Bid%5D=1757E1D7FD5E410A9C563024250015BF&
data%5Bstatus%5D=pending&data%5Baccount_id%5D=70CA234077134ED0BF2E0E46B0EDC36F&
data%5Bsubscription_id%5D=F4115E5E28AE4CCA941FCCCCCABE9A0A
Which translates to:
event = invoice.created
data[id] = 1757E1D7FD5E410A9C563024250015BF
data[status] = pending
data[account_id] = 70CA234077134ED0BF2E0E46B0EDC36F
data[subscription_id] = F4115E5E28AE4CCA941FCCCCCABE9A0A
Code:
#PostMapping(consumes = [MediaType.APPLICATION_FORM_URLENCODED_VALUE])
fun cb(event: SubscriptionRenewed)
{
println(event)
}
data class SubscriptionRenewed(
val event: String,
val data: Data
)
data class Data(
val id: String,
val status: String,
val account_id: String,
val subscription_id: String
)
Normally you just create a POJO representation of the incoming body and spring a translates it to an object.
I learned that I could add all the parameters to the function declaration as #RequestParam("data[id]") id: String, but that would make things really verbose.
The issue is with parsing data[*], ideas of how to make it work?
Edit:
I discovered that if I change val data: Data to val data: Map<String, String> = HashMap(), the associative array will be correctly inserted into the map, ideas of how to map it to an object instead?
Note: IDs/Tokens are not real. They are from a documentation snippet.
Deserialize to Map and use json serialize/deserialize to object
Initially deserialize the input to Map<String, String>
Use Json processor(like ObjectMapper or Gson) to serialize the Map constructed in the previous step
Use the json processor to deserialize the json output of previous step to a custom object.
static class Data {
private String one;
private String a;
#Override
public String toString() {
return "Data{one=" + one + ", a=" + a + "}";
}
}
public static void main(String[] args) {
String input = "{\"one\":1, \"a\":\"B\"}";
Gson gson = new GsonBuilder().create();
Map<String, String> map = gson.fromJson(input, new TypeToken<Map<String, String>>(){}.getType());
Data data = gson.fromJson(gson.toJson(map), Data.class);
System.out.println(data);
}
This is surely a round about approach and i am not aware of any optimization
I want to convert each integer/double value to String present in json request before storing in MongoDB database.
There can be multiple fields like amountValue in the json. I am looking for a generic way which can parse json with any number of such attributes value to string. My request will have around 200 fields.
ex: "amountValue": 200.00, to "amountValue": "200.00",
{
"templateName": "My DC Template 14",
"templateDetails": {
"beneficiaryName": "Snow2",
"dcOpenAmount": {
"amountValue": 200.00,
}
}
}
My mongoDB Document is of the form
#Document
public class TemplateDetails {
#Id
private long templateId;
private String templateName;
private Object templateDetail;
}
Because we are storing document in mongodb as an object(Which can accept any type of json request) we dont have field level control on it.
In my controller, converting the request object to json.
This is how I tried. But its not meeting my expectation. It is still keeping the amount value to its original double form.:
ObjectMapper mapper = new ObjectMapper();
try {
String json = mapper.writeValueAsString(templateRequestVO);
System.out.println("ResultingJSONstring = " + json);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
Output :
ResultingJSONstring = {"id":null,"userId":"FU.ZONKO","txnType":"LCI","accessIndicator":"Public","templateId":null,"templateName":"My DC Template 14","tags":null,"templateDetails":{"applicantDetail":{"applicantName":"Tom","applicantAddress":{"addressLine1":"Infosys, Phase 2","city":"PUNE","state":"MAHARASHTRA","country":"INDIA","zip":"40039"},"accountId":"Account1234","customerId":"JPMORGAN"},"beneficiaryName":"Snow2","dcOpenAmount":{"amountValue":200.0,"currency":"USD"}}}
Is there any way to accomplish the result ? Or anything which can help to store documents in mongodb with attribute type as String ?
You can use Json manipulation avaliable in "org.json.JSONObject" to convert Double value to Stirng .
If your Json structure won't change and will remain as said above , you can do the following.
import org.json.JSONObject;
public static void main(String args[]) {
String j = "{ \"templateName\": \"My DC Template 14\", \"templateDetails\": { \"beneficiaryName\": \"Snow2\", \"dcOpenAmount\": { \"amountValue\": 200.00 } } }";
JSONObject jo = new JSONObject(j);
jo.getJSONObject("templateDetails")
.getJSONObject("dcOpenAmount")
.put("amountValue", String.valueOf(jo.getJSONObject("templateDetails").getJSONObject("dcOpenAmount").getDouble("amountValue")));
System.out.println(jo.toString());
}
Following will be the output
{"templateDetails":{"dcOpenAmount":{"amountValue":"200.0"},"beneficiaryName":"Snow2"},"templateName":"My DC Template 14"}
I don't know for mongodb but for a json string you can replace them with a regex and the function replace like this :
public class Test {
public static void main(String[] args) {
String json = "{\"id\":null,\"userId\":\"FU.ZONKO\",\"txnType\":\"LCI\",\"accessIndicator\":\"Public\",\"templateId\":null,\"templateName\":\"My DC Template 14\",\"tags\":null,\"templateDetails\":{\"applicantDetail\":{\"applicantName\":\"Tom\",\"applicantAddress\":{\"addressLine1\":\"Infosys, Phase 2\",\"city\":\"PUNE\",\"state\":\"MAHARASHTRA\",\"country\":\"INDIA\",\"zip\":\"40039\"},\"accountId\":\"Account1234\",\"customerId\":\"JPMORGAN\"},\"beneficiaryName\":\"Snow2\",\"dcOpenAmount\":{\"amountValue\":200.0,\"currency\":\"USD\"}}}";
System.out.println(replaceNumberByStrings(json));
}
public static String replaceNumberByStrings(String str){
return str.replaceAll("(?<=:)\\d+(\\.\\d+)?(?=(,|}))","\"$0\"");
}
}
It will look for all fields with a numeric value in the json string and add quotes to the value. This way they will be interpreted as strings when the json willl be parsed.
It will not work if the value is in an array though, but in this case it should not be a problem.
I have a DTO class like this:
package stbet.model.dto.db;
public class UKDashboardEventDTO implements Serializable{
private Long eventId;
private String meetingCode;
private String meetingName;
private String eventTime;
private String eventCode;
private String settleStatus;
private String category;
//getters and setters here:
#Override
public String toString() {
return "eventList{" + "eventId=" + eventId + ", meetingCode=" + meetingCode + ", meetingName=" + meetingName
+ "eventTime=" + eventTime + ", eventCode=" + eventCode + ", settleStatus=" + settleStatus
+ ", category=" + category + '}';
}
}
and I do some query stuff and create a java List of above DTO type.
for(Event ev : eventList){
dto = new UKDashboardEventDTO();
// some stuff
dto.setEventCode(ev.getEventCode());
dto.setEventId(ev.getId());
dto.setEventTime(ev.getEventTime());
dto.setMeetingName(ev.getMeeting().getMeetingName());
dto.setMeetingCode(ev.getMeeting().getMeetingCode());
eventDTOList.add(dto);
}
Then I add this list into a Hashmap and covert it into a JSON object like this:
Map map = new HashMap();
map.put("eventList",eventDTOList);
now convert into the json:
JSONObject obj = new JSONObject();
try {
obj.put("eventMap", map);
} catch (JSONException ex) {
}
out.println(obj);
out.flush();
out.close();
but when I get this object from client side, I am getting the dto package/object names list when parse or stringify the output instead of the proper dto values I passed from Java. What I get is this:
"{"eventMap":{"eventList":["stbet.model.dto.db.UKDashboardEventDTO#617538bb","stbet.model.dto.db.UKDashboardEventDTO#56dfaef9","stbet.model.dto.db.UKDashboardEventDTO#775889fd","stbet.model.dto.db.UKDashboardEventDTO#55cb7e41","stbet.model.dto.db.UKDashboardEventDTO#22ce0968","stbet.model.dto.db.UKDashboardEventDTO#4cb9cb2"]}}"
can you please let me know how to get the dto values I set from Java to client side json without java package name as above.
Firstly, you're using both JSON and GSON libraries, JSONException exists in JSON one and Expose annotation is in GSON. Please make sure you don't mix them as I won't work as intended.
Secondly, from Expose documentation
An annotation that indicates this member should be exposed for JSON serialization or deserialization.
This annotation has no effect unless you build Gson with a GsonBuilder and invoke GsonBuilder.excludeFieldsWithoutExposeAnnotation() method.
You should Override the toString field on the DTO, to print out all the individual field values.
This toString will be called when you do out.println(obj);
eg.
toString() {
// this method should list out all the attributes.
}
You should be using GSONBuilder to create the gson. Examples:
Gson: How to exclude specific fields from Serialization without annotations
Gson doesn't parse an exposed field
Here is a post on using GSON also
How to expose a method using GSon?
Finally I could fix it with your suggestions #Trynkiewicz Mariusz and #Paul John.
What I did was:
1. remove #Expose annotation
2. overridden the toString(){...} method.
3. remove the map implementation and used a List.
4. used gson.toJson(eventList);
this solved the issue and the output now is like :
[{
"eventId":167804,
"meetingCode":"V5PGB",
"meetingName":"SprintValley",
"eventTime":"15:38:00",
"eventCode":"10:08:00",
"category":"HR"
},
{
"eventId":167805,
"meetingCode":"V5PGB",
"meetingName":"SprintValley",
"eventTime":"15:50:00",
"eventCode":"10:20:00",
"category":"HR"
},..]
Thanks again guys...