Saving List<T> as String - java

I've been trying to save a list of data as Strings, but when I try a method .toString on List, it returns address in memory instead of data.
public class Item {
Integer price = 20;
Integer modelNumber = 100;
String description = "Description";
String title = "Title";
Boolean wasBought = true;
}
public static void main(String[] args) {
List<Item> data = new ArrayList<>();
data.add(new Item());
System.out.println(data.toString());
}

You need to override toString function in your Item class. Add the following snippet into your Item class:
#Override
public String toString() {
return "Item{" +
"price=" + price +
", modelNumber=" + modelNumber +
", description='" + description + '\'' +
", title='" + title + '\'' +
", wasBought=" + wasBought +
'}';
}
Output:
[Item{price=20, modelNumber=100, description='Description', title='Title', wasBought=true}]

You can convert List to json format string by json utils, e.g. jackson or fastjson, in case you may need to convert it to Objects later.

Simply use Lombok (Add Lombok jar into classpath) #ToString annotate for Item class, it will do the needful output https://projectlombok.org/features/ToString

Related

Why do I get, and how do I solve this "String to object of type <objecttype>" error

I am (being an absolute beginner), trying to create a simple tool, that creates some objects and links them.
The objects are:
Customers
Licenses (2 types, extends class)
The idea is to use (one of) the customer company name when creating a license, so the license is linked to a customer.
I use ArrayLists to store the data.
I tried to use the getter for Customer cCompany, but when I try to actually create a new license object, I get errors about incompatible types (String to object of type customer)
How can I fix that error?
Any help is highly appreciated, but please explain well, me being an absolute beginner. I probably overcomplicate stuff....
Some code extracts:
From Main:
public class Main {
public static void main(String[] args) {
//Create customers
List <Customer> customers = new ArrayList <> (10);
customers.add(new Customer("TestCompany","John Doe",1234567890,"John#testcompany.com"));
....
//Create Elvis licenses (based on superclass License)
List <ElvisLicense> ellicenses = new ArrayList <> (10);
ellicenses.add(new ElvisLicense("TestCompany","VendorA",1234,"1234-A","Solutions Server gold","1234-dtbk-87654-nlof",10, true , true));
Class: Customer:
class Customer {
String cCompany;
private String cName;
private int cPhone;
private String cEmail;
public Customer( String cCompany, String cName,int cPhone, String cEmail)
{
this.cCompany = cCompany;
this.cName = cName;
this.cPhone = cPhone;
this.cEmail = cEmail;
}
//This getter should be used to link the license to the customer (Done in License.java)
public String getcCompany() {
return cCompany;
}
Class License (Superclass)
class License {
// Used no modifier to set access for Class/Package and Subclass inside the package
Customer licenseCompany;
String lVendor;
int lContractNumber;
String lCertificateNumber;
String lProductName;
String lLicenseKey;
int lNumberOfSeats;
public License(Customer cCompany, String lVendor, int lContractNumber, String lCertificateNumber,
String lProductName, String lLicenseKey, int lNumberOfSeats)
{
licenseCompany = cCompany;
this.lVendor = lVendor;
this.lVendor = lVendor;
this.lContractNumber = lContractNumber;
this.lCertificateNumber = lCertificateNumber;
this.lProductName = lProductName;
this.lLicenseKey = lLicenseKey;
this.lNumberOfSeats = lNumberOfSeats;
}
public Customer getLicenseCompany() {
return licenseCompany;
}
public void setLicenseCompany(Customer licenseCompany) {
this.licenseCompany = licenseCompany;
}
//preparations to allow for example printing the content of an arraylist element
#Override
public String toString(){
return "Customer name " + getLicenseCompany() + "\n" + "Vendor name " + getlVendor() + "\n" + "Contract number: " + getlContractNumber() + "\n"
+ "Certificate number: " + getlCertificateNumber() + "\n" +
"Product name " + getlProductName() + "\n" + "Licence key: " + getlLicenseKey() + "\n"
+ "Number of seats: " + getlNumberOfSeats();
}
}
And the extended class:
public class ElvisLicense extends License{
private boolean elIsBundle;
private boolean elIsSubscription;
public ElvisLicense(
Customer licenseCompany,
String lVendor,
int lContractNumber,
String lCertificateNumber,
String lProductName,
String lLicenseKey,
int lNumberOfSeats,
boolean elIsBundle,
boolean elIsSubscription
)
{
super(
licenseCompany,
lVendor,
lContractNumber,
lCertificateNumber,
lProductName,
lLicenseKey,
lNumberOfSeats);
this.elIsBundle = elIsBundle;
this.elIsSubscription = elIsSubscription;
}
.....
#Override
public String toString(){
return "Customer name " + licenseCompany + "\n"
+ "Vendor name " + lVendor + "\n"
+ "Contract number: " + lContractNumber + "\n"
+ "Certificate number: " + lCertificateNumber + "\n"
+ "Product name " + lProductName + "\n"
+ "Licence key: " + lLicenseKey + "\n"
+ "Number of seats: " + lNumberOfSeats + "\n"
+ "Number of seats: " + elIsBundle + "\n"
+ "Number of seats: " + elIsSubscription;
}
}
I expect that the Customername is used when creating a new license.
Below line is wrong.
ellicenses.add(new ElvisLicense("TestCompany","VendorA",1234,"1234-A","Solutions Server gold","1234-dtbk-87654-nlof",10, true , true));
As license need customer object an parameter. Instead, you should create customer object first.
ellicenses.add(new ElvisLicense(new Customer("TestCompany","VendorA",1234,"1234-A"),"Solutions Server gold","1234-dtbk-87654-nlof",10, true , true));
for reusing that customer list to avoid create company.
for(Customer customer : customers){
// here you need some way to offer other parameters except customer parameter.
License license = new new ElvisLicense(customer,"Solutions Server gold","1234-dtbk-87654-nlof",10, true , true);
ellicenses.add(license);
}
What you need to do is to use one of the Customer objects you have already created when creating the ElvisLicense object. To more easily find that customer by name I suggest you store them in a map instead of a list with the name as a key.
Map<String, Customer> customerMap = new HashMap<>();
Customer customer = new Customer("TestCompany","John Doe",1234567890,"John#testcompany.com"));
customerMap.put(customer.getcCompany(), customer);
so when creating the license you look up the customer
List <ElvisLicense> ellicenses = new ArrayList <> (10);
Customer customer = customerMap.get("TestCompany");
if (customer != null) {
ElvisLicense license = new ElvisLicense(customer,"VendorA",1234,"1234-A","Solutions Server gold","1234-dtbk-87654-nlof",10, true , true));
ellicenses.add(license);
} else {
//If the customer isn't found you need some kind of error handling, better than below :)
System.out.println("Can't create a license, no customer found");
}

OpenCSV flat to hierarchy structure data parsing

I need advice on the issue which I am facing while parsing CSV data in java.
I have a CSV file with data in below format
name, gender, address_first_line, address_second_line, city, number
me, Male, anonymous, random, Auckland, 6545
other, Female, random, anon, Auckland, 6688
I want to parse the CSV file using the openCSV library in below Object Model. I am aware of parsing single class but facing issues while parsing data when multiple classes are involved. Please suggest if there is any other library available which can help me to get the desired result.
Class User {
String name;
String gender;
Address address;
long number;
}
Class Address {
String firstLine;
String secondLine;
}
univocity-parsers has a #Nested annotation you can use:
Try this:
public static class User {
#Parsed
String name;
#Parsed
String gender;
#Nested
Address address;
#Parsed
long number;
#Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", gender='" + gender + '\'' +
", address=" + address +
", number=" + number +
'}';
}
}
public static class Address {
#Parsed(field = "address_first_line")
String firstLine;
#Parsed(field = "address_second_line")
String secondLine;
#Override
public String toString() {
return "Address{" +
"firstLine='" + firstLine + '\'' +
", secondLine='" + secondLine + '\'' +
'}';
}
}
public static void main(String ... args){
StringReader input = new StringReader(
"name,gender,address_first_line,address_second_line, city,number\n" +
"John,M,Somewhere,Else,City,1");
for(User user : new CsvRoutines().iterate(User.class, input)){
System.out.println(user.toString());
}
}
Output:
User{name='John', gender='M', address=Address{firstLine='Somewhere', secondLine='Else'}, number=1}
If you don't like annotations you can map things manually:
CsvRoutines routines = new CsvRoutines();
ColumnMapper mapper = routines.getColumnMapper();
mapper.attributeToColumnName("name", "name");
mapper.attributeToColumnName("gender", "gender");
mapper.attributeToColumnName("number", "number");
mapper.attributeToColumnName("address.firstLine", "address_first_line");
mapper.attributeToColumnName("address.secondLine", "address_second_line");
for (User user : routines.iterate(User.class, input)) {
System.out.println(user.toString());
}
Hope it helps.
Disclaimer: I'm the author of this lib. It's open-source and free (Apache 2.0 license)

Jackson does not store xml values in object

I have an XML file like this:
"<?xml version ='1.0' encoding='UFT-8'?>"+
"<CLOSE_TRAILER>"+
"<user>" +
"<id>0600580</id>" +
"<trans_id>7</trans_id>" +
"<host_name>Mnull</host_name>"+
"<session_token>79430831Zahyy</session_token>" +
"<time_stamp>1551736026682</time_stamp>" +
"</user>"+
"<trailer_detail>" +
"<org_id>432</org_id>" +
"<trailer_prefix>XTRA</trailer_prefix>" +
"<system_type>SCAN</system_type>" +
"<truck_mail_flag>false</truck_mail_flag>" +
"<trailer_type_code>T</trailer_type_code>" +
"<in_contingency_flag>false</in_contingency_flag>" +
"<detl_code_svc_type>OVN</detl_code_svc_type>" +
"<catg_code_svc_type></catg_code_svc_type>" +
"<seal_number>12345</seal_number>" +
"<user_id>5155035</user_id>" +
"<trailer_number>24813</trailer_number>" +
"</trailer_detail>"+
"<load_handler>" +
"<employee_id>TEST</employee_id>" +
"<trailer_load_seq>71373839</trailer_load_seq>" +
"<action_code></action_code>" +
"</load_handler>"+
"</CLOSE_TRAILER>";
I want to map the trailer_detail and load_handler but not user, it into this object that I created for this xml:
#JsonRootName(value = "CLOSE_TRAILER")
public class CloseTrailerXml {
#JsonUnwrapped
Trailer trailer_detail;
#JsonUnwrapped
LoadHandler load_handler;
}
The Trailer class I have mapped like this:
#JsonRootName("trailer_detail")
public class Trailer {
private Integer equipmentSeq;
private String createdBy;
private ZonedDateTime createdDt;
private String updatedBy;
private ZonedDateTime updatedDt;
#JsonProperty("trailer_number")
private String trlrNbr;
... more member variables
In a unit test case I have the above xml stored as a string and I use this code below to map it into the object:
String msgNoNewLineChar = originalScannerMsg.replace("\\n","");
String msgNoCarReturnChar = msgNoNewLineChar.replace("\\r", "");
XmlMapper xmlMapper = new XmlMapper();
xmlMapper.setSerializationInclusion(Include.NON_NULL);
CloseTrailerXml closeTrailerXml= xmlMapper.readValue(originalScannerMsg, CloseTrailerXml.class);
The closeTrailerXml is created but all values are null.
If I remove the encoding line and CLOSE_TRAILER tag and the user section, it maps fine.
Why can't the object mapper work with the user section present?

jackson deserialize array into a java object

I have json'ed array of host, port, uri tuples encoded by 3rd party as an array of fixed length arrays:
[
["www1.example.com", "443", "/api/v1"],
["proxy.example.com", "8089", "/api/v4"]
]
I would like to use jackson magic to get a list of instances of
class Endpoint {
String host;
int port;
String uri;
}
Please help me to put proper annotations to make ObjectMapper to do the magic.
I do not have control on the incoming format and all my google'n ends in answers on how to map array of proper json objects (not arrays) into list of objects (like https://stackoverflow.com/a/6349488/707608)
=== working solution as advised by https://stackoverflow.com/users/59501/staxman
in https://stackoverflow.com/a/38111311/707608
public static void main(String[] args) throws IOException {
String input = "" +
"[\n" +
" [\"www1.example.com\", \"443\", \"/api/v1\"],\n" +
" [\"proxy.example.com\", \"8089\", \"/api/v4\"]\n" +
"]";
ObjectMapper om = new ObjectMapper();
List<Endpoint> endpoints = om.readValue(input,
new TypeReference<List<Endpoint>>() {});
System.out.println("endpoints = " + endpoints);
}
#JsonFormat(shape = JsonFormat.Shape.ARRAY)
static class Endpoint {
#JsonProperty() String host;
#JsonProperty() int port;
#JsonProperty() String uri;
#Override
public String toString() {
return "Endpoint{host='" + host + '\'' + ", port='" + port + '\'' + ", uri='" + uri + '\'' + '}';
}
}
Add following annotation:
#JsonFormat(shape=JsonFormat.Shape.ARRAY)
class Endpoint {
}
and it should serialize entries as you wish.
Also: it'd be safest to then use #JsonPropertyOrder({ .... } ) to enforce specific ordering, as JVM may or may not expose fields or methods in any specific order.
Consider importing the two dimensional array and then running through a loop. Then you can have a constructor on the Endpoint class that accepts each instance of internal array.

Looking for a Straightforward Way to Parse JSON

I am attempting to parse the following JSON using Java:
{ "student_id": "123456789", "student_name": "Bart Simpson", "student_absences": 1}
What is the simplest way to accomplish this. I tried doing it the way below but think there must be an easier way.
import org.json.*
JSONObject obj = new JSONArray("report");
for(int i = 0; I < arr.length(); i++){
String studentname =
arr.getJSONObject(i).getString("student_id");
arr.getJSONObject(i).getString("student_name");
arr.getJSONObject(i).getString("student_name");
}
There's Gson:
import com.google.gson.Gson;
import com.google.gson.annotations.SerializedName;
public class Main {
public static void main(String[] args) {
String json = "{ \"student_id\": \"123456789\", \"student_name\": \"Bart Simpson\", \"student_absences\": 1}";
Student student = new Gson().fromJson(json, Student.class);
System.out.println(student);
}
}
class Student {
#SerializedName("student_id")
String studentId;
#SerializedName("student_name")
String studentName;
#SerializedName("student_absences")
Integer studentAbsences;
#Override
public String toString() {
return "Student{" +
"studentId='" + studentId + '\'' +
", studentName='" + studentName + '\'' +
", studentAbsences=" + studentAbsences +
'}';
}
}
Another popular one is Jackson:
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.ObjectMapper;
public class Main {
public static void main(String[] args) throws Exception {
String json = "{ \"student_id\": \"123456789\", \"student_name\": \"Bart Simpson\", \"student_absences\": 1}";
Student student = new ObjectMapper().readValue(json, Student.class);
System.out.println(student);
}
}
class Student {
#JsonProperty("student_id")
String studentId;
#JsonProperty("student_name")
String studentName;
#JsonProperty("student_absences")
Integer studentAbsences;
#Override
public String toString() {
return "Student{" +
"studentId='" + studentId + '\'' +
", studentName='" + studentName + '\'' +
", studentAbsences=" + studentAbsences +
'}';
}
}
In both cases, running Main will print:
Student{studentId='123456789', studentName='Bart Simpson', studentAbsences=1}
EDIT
And without creating a Student class, you could give something like JsonPath a try.
The answer to your question depends on what you want to achieve. Your example would result in an array of strings. The previous answer results in a Java class with a property for each field. Another option is to put the values into a map.
If have written an encoder / decoder combination for this. Encoding is quite easy: use the keys and values of the map. The decoder (JSON string to map or anything else) requires a parser (best would be a tokenizer).

Categories