Converted json (from ArrayList) has more elements - java

I post what I have done, as I don't get the result.. Here I have a method which returns an ArrayList:
public ArrayList<Label> getLabels()
throws ClassNotFoundException, SQLException{
ArrayList<Label> labels = new ArrayList<>();
sq = "SELECT * from LABELS";
try {
Class.forName(typeDB);
c = DriverManager.getConnection(path);
stm = c.prepareStatement(sq);
ResultSet rs = stm.executeQuery();
while(rs.next()) {
Label label = new Label(rs.getString("type"), rs.getString("description"),rs.getString("product")+"-"+rs.getString("version"), rs.getString("cutter"));
labels.add(label);
}
} catch (SQLException e) {
System.out.println(e.getMessage());
} finally {
if (stm != null)
stm.close();
if (c != null)
c.close();
}
System.out.println("Label "+ labels.size());
return labels;
}
then I want covert this ArrayList to JSON format. So I execute labelsToJSON(action.getLabels()); where:
public void labelsToJSON(ArrayList<Label> list){
ObjectMapper mapper = new ObjectMapper();
try{
mapper.writeValue(new File("C:\\temp\\labels.json"), list);
}catch(JsonGenerationException e){
e.printStackTrace();
}catch(JsonMappingException e){
e.printStackTrace();
}catch (IOException e){
e.printStackTrace();
}
}
}
The Label class is defined:
public class Label {
private String barcode;
private String labelCode;
private String productCode;
private String type;
//and many others..
public Label(){
}
//This is the costructor I use above in the method
public Label(String type, String description, String productCode, String cutter) {
this.type = type;
this.description = description;
this.productCode = productCode;
this.cutter = cutter;
}
//and then some other constructors (I post 2 for example)
public Label(String type, String description, String product, String version, String cutter) {
this.type = type;
this.description = description;
this.product = product;
this.version = version;
this.cutter = cutter;
}
public Label(String barcode, String product, String version, String dateProduction, String order , int quantity, String packetNumber, String type, String description, String cutter) {
this.barcode = barcode;
this.product = product;
this.version = version;
this.dateProduction = dateProduction;
this.order = order;
this.packetNumber = packetNumber;
this.quantity = quantity;
this.type = type;
this.description = description;
this.cutter = cutter;
}
//setters, getters etc
So, I create an object from the constructor with parameters String type, String description, String productCode, String cutter. However the labels.json contains these data
[{
"barcode":null,
"labelCode":null,
"productCode":"111123123-1123", //<-
"type":"Container", //<-
"description":"this is a description", //<- all these I was expected.
"cutter":"1031", //<-
"date":null,
"time":null,
"dateProduction":null,
"order":null,
"product":null,
"version":null,
"packetNumber":null,
"quantity":0
}, //and so on
I don't understand why the json file has so many attributes?? My objects supposed to have only 4 --> String type, String description, String productCode, String cutter

ObjectMapper will by default serialise all field values on a class, regardless of whether they are null or not so you get everything from your Label class.
To only serialise non null values that you can configure the ObjectMapper see the JavaDoc for setSerializationInclusion and Include
mapper.setSerializationInclusion(Include.NON_NULL);
EDIT:
As Maraboc pointed out you have the problem with quantity still being serialised when using the Include.NON_NULL. For finer grain control of which fields are serialised you can use #JsonIgnore annotation to prevent the other fields in your class from being serialised.
Or you can add #JsonIgnoreProperties({"quantity"}) to your class

You can define your Label class with JsonSerialize annotation and change the type of quantity from primitive int to Integer Object. If type is int, the default value zero will be assigned to the variable.
#JsonSerialize(
include=JsonSerialize.Inclusion.NON_NULL)
public class Label {
// ...other properties
private Integer quantity;
public Integer getQuantity() {
return quantity;
}
public void setQuantity(Integer quantity) {
this.quantity = quantity;
}
}

Related

gson deserializing a field as null

First of all, I'd like to say this is for a university project.
I have 3 classes. Order abstract class and Delivery and DineIn classes which inherits from Order.
I am using Gson to serialize/deserialize the child classes but I have run into a bit of a problem. The Order class has a field orderType which gson uses to determine type of order it is, DineIn or Delivery.
Serialization is working just fine. The problem is that whenever I try to deserialize, the type field value is not read and is always set as null even though it is present in the JSON file.
This happens when there are a lot of fields in Order because when I tried testing this program on a smaller scale with the Order class just having 2 fields (orderType and orderNo) everything worked just fine. I don't what I am doing wrong. I have tried searching on this site and am almost always coming across suggestions to make custom type adapters and serializers but we haven't studied about them in university and I don't want to use them (the instructor deducts marks for using anything he hasn't taught, I almost failed a course I took from him last time because I used things he hadn't taught. He doesn't seem to have a problem with third-party libraries though).
The code:
public class Main {
public static final List<Order> ordersList = read();
public static void main(String[] args) {
System.out.println(ordersList.get(0).getOrderType());
System.out.println(ordersList.get(0) instanceof DineIn ? "DineIn": "Delivery");
}
private static List<Order> read(){
List<Order> ordersList = new ArrayList<>();
Type type = new TypeToken<ArrayList<Order>>() {
}.getType();
RuntimeTypeAdapterFactory<Order> adapter = RuntimeTypeAdapterFactory.of(Order.class, "orderType")
.registerSubtype(DineIn.class)
.registerSubtype(Delivery.class);
Gson gson = new GsonBuilder().registerTypeAdapterFactory(adapter).create();
JsonReader ordersJsonReader;
try {
ordersJsonReader = new JsonReader(new FileReader("orders.json"));
List<Order> tempOrdersList = gson.fromJson(ordersJsonReader, type);
if (tempOrdersList != null) ordersList = tempOrdersList;
ordersJsonReader.close();
} catch (IOException e) {
e.printStackTrace();
}
return ordersList;
}
}
abstract class Order {
private final int orderNumber;
private final String date, customerName;
private final int discountRate;
private final String paymentMethod;
private String orderStatus;
private int grossTotal = 0;
private double netTotal = 0;
private int totalItems = 0;
protected final String orderType;
public abstract String getOrderType();
public abstract double getExtraCharges();
public Order(int orderNumber, String date, String customerName, int discountRate, String paymentMethod, String orderStatus, int grossTotal, double netTotal, int totalItems, String orderType) {
this.orderNumber = orderNumber;
this.date = date;
this.customerName = customerName;
this.discountRate = discountRate;
this.paymentMethod = paymentMethod;
this.orderStatus = orderStatus;
this.grossTotal = grossTotal;
this.netTotal = netTotal;
this.totalItems = totalItems;
this.orderType = orderType;
}
}
class DineIn extends Order {
private double serviceCharges = 150;
public DineIn(int orderNumber, String date, String customerName, int discountRate, String paymentMethod, String orderStatus, int grossTotal, double netTotal, int totalItems) {
super(orderNumber, date, customerName, discountRate, paymentMethod, orderStatus, grossTotal, netTotal, totalItems, "DineIn");
}
#Override
public String getOrderType() {
return orderType;
}
#Override
public double getExtraCharges() {
return serviceCharges;
}
}
class Delivery extends Order {
private double deliveryCharges = 100;
public Delivery(int orderNumber, String date, String customerName, int discountRate, String paymentMethod, String orderStatus, int grossTotal, double netTotal, int totalItems) {
super(orderNumber, date, customerName, discountRate, paymentMethod, orderStatus, grossTotal, netTotal, totalItems, "Delivery");
}
#Override
public String getOrderType() {
return orderType;
}
#Override
public double getExtraCharges() {
return deliveryCharges;
}
}
The JSON:
[
{
"serviceCharges": 150.0,
"orderNumber": 1,
"date": "12/12/2021",
"customerName": "Ali",
"discountRate": 15,
"paymentMethod": "Card",
"orderStatus": "Preparing",
"grossTotal": 5000,
"netTotal": 4500.0,
"totalItems": 14,
"orderType": "DineIn"
}
]
In your code you have a hierarchy where DineIn and Delivery extend from Order. The way the orderType field is set is through an explicit String argument in the super() constructor.
However, Gson does not use the constructor to instantiate the objects. It uses a special no-argument constructor and populates the values via reflection: https://stackoverflow.com/a/40442037/9698467
In this specific case the problem comes from the RuntimeTypeAdapterFactory, which removes the orderType field from the JSON that it reads. The source code here confirms that: https://github.com/google/gson/blob/86d88c32cf6a6b7a6e0bbc855d76e4ccf6f120bb/extras/src/main/java/com/google/gson/typeadapters/RuntimeTypeAdapterFactory.java#L202
As #fluffy suggested newer versions of the library include the maintain flag, which should allow for the field to be preserved: https://github.com/google/gson/blob/c1e7e2d2808b042cbe47ca31869ee6ccc62c5417/extras/src/main/java/com/google/gson/typeadapters/RuntimeTypeAdapterFactory.java#L214

JavaFX tableview bag on java when i parse and input data from sql

The Tableview does not completely output data from the sql table, although there are no errors. That is, the problem is that the program outputs only part of the data, although there are some in the sheet itself
SQL query class (sqlworker)
public List<String> gettableManagmet() throws SQLException {
resSet = statmt.executeQuery("PRAGMA TABLE_INFO('Users');");
List<String> ls = new ArrayList<>();
while (resSet.next()) {
ls.add(resSet.getString("name"));
}
System.out.println(ls);
return ls;
}
public ObservableList<Users> getdatausermanagment() throws SQLException {
ObservableList<Users> res = FXCollections.observableArrayList();
resSet = statmt.executeQuery("SELECT * FROM Users");
while (resSet.next()) {
String id = String.valueOf(resSet.getInt("id"));
String Login = resSet.getString("Login");
String Pass = resSet.getString("Pass");
String Otel = resSet.getString("Otel");
String isManager = String.valueOf(resSet.getInt("isManager"));
String isAdmin = String.valueOf(resSet.getInt("isAdmin"));
String isBlocked = String.valueOf(resSet.getInt("isBlocked"));
String CauseBlocking = resSet.getString("CauseBlocking");
System.out.println(id+ Login+Pass+Otel+isManager+isAdmin+isAdmin+CauseBlocking);
res.add(new Users(id,Login,Pass,Otel,isManager,isAdmin,isBlocked,CauseBlocking));
}
for(Users s : res){
System.out.println(s);
}
return res;
}
public void adddata(TableView table) throws SQLException {
ObservableList<Users> res = FXCollections.observableArrayList();
resSet = statmt.executeQuery("SELECT * FROM Users");
while (resSet.next()) {
String id = String.valueOf(resSet.getInt("id"));
String Login = resSet.getString("Login");
String Pass = resSet.getString("Pass");
String Otel = resSet.getString("Otel");
String isManager = String.valueOf(resSet.getInt("isManager"));
String isAdmin = String.valueOf(resSet.getInt("isAdmin"));
String isBlocked = String.valueOf(resSet.getInt("isBlocked"));
String CauseBlocking = resSet.getString("CauseBlocking");
System.out.println(id+ Login+Pass+Otel+isManager+isAdmin+isAdmin+isBlocked+CauseBlocking);
table.getItems().add(new Users(id,Login,Pass,Otel,isManager,isAdmin,isBlocked,CauseBlocking));
}
}
Users class
private final String id;
private final String login;
private final String pass;
private final String otel;
private SimpleStringProperty isManager;
private final String isAdmin;
private final String isBlocked;
private final String causeBloocking;
public Users(String id, String login, String pass, String otel, String isManager, String isAdmin, String isBlocked, String causeBlocking) {
this.id = id;
this.login = login;
this.pass = pass;
this.otel = otel;
this.isManager = new SimpleStringProperty(isManager);
this.isAdmin = isAdmin;
this.isBlocked = isBlocked;
this.causeBloocking = causeBlocking;
}
public String getId() {
return id;
}
public String getLogin() {
return login;
}
public String getPass() {
return pass;
}
public String getOtel() {
return otel;
}
public String getisManager() {
return isManager.get();
}
public String getisAdmin() {
return isAdmin;
}
public String getisBlocked() {
return isBlocked;
}
public String getCauseBloocking() {
return causeBloocking;
}
Class where i parse data
public TableView table;
#Override
public void initialize(URL location, ResourceBundle resources) {
SQLWorker sqlWorker = new SQLWorker();
table.setEditable(true);
try {
for (String s: sqlWorker.gettableManagmet()) {
TableColumn<Users, String> tb = new TableColumn<>(s);
tb.setCellValueFactory(new PropertyValueFactory<>(s));
tb.setCellFactory(TextFieldTableCell.forTableColumn());
tb.setVisible(true);
table.getColumns().addAll(tb);
System.out.println(tb.getProperties());
}
System.out.println(table.getColumns().size());
sqlWorker.adddata(table);
} catch (SQLException e) {
e.printStackTrace();
}
}
fxml file
enter image description here
when programme in work
enter image description here
sql database enter image description here
The issues here are
you do not adhere to the Java naming conventions for 3 of your getters; PropertyValueFactory relies on those: the property passed to the constructor is modified by converting the first letter to upper case and then PropertyValueFactory checks for methods with that modified name prefixed with get or is. It e.g. looks for getIsManager() or isIsManager() not for getisManager(). (Note that this is much easier to read btw.)
There's a typo in one of your getter (and the corresponding field) names: It should be getCauseBlocking(), not getCauseBloocking()

Convert pojo (list of object) to json in java using jackson

I'm facing a problem while converting simple JSON to POJO object.
This is my code:
public class Products {
private int id;
private String type;
private String description;
private Double price;
private String brand;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public Double getPrice() {
return price;
}
public void setPrice(Double price) {
this.price = price;
}
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
}
Im getting below as output:
com.ObjectToJson.Product#b97c004
Object to Json --> {
"products" : null
}
I am not able to convert JSON to/from Java Objects using JACKSON API.
Please, can anyone help me out on this?
Where is the code where you try to create the JSON from your object? Without it, it will be hard to say what to fix. The problem may also be coming from the fact that your Products class has no constructor. So when you make an object its nothing. You should add a constructor after you initialize your variables like:
public Products(){
}
Then try making your JSON from the object, which should be something like:
Products p = new Products();
ObjectMapper mapper = new ObjectMapper();
String JSON = mapper.writeValueAsString(p); // to get json string
mapper.readValue(JSON, Products.class); // json string to obj
Be sure to set your Product's object variables using setters or getters, or to initialize them to values by adding parameters to your constructor:
public Products(String type, String description, Double price,
String brand){
this.type = type;
this.description = description; //etc etc...
}

Store Java enum's String value instead of enum value itself in DynamoDB

I'm using DynamoDB and I would like to store the enum's String values instead of the enum itself.
For instance, I have this enum:
public enum Source {
BREACH("breach"),
LEAKAGE("leakage");
private final String desc;
Source(String desc) { this.desc = desc; }
public String desc() { return desc; }
}
...and this "entity":
#DynamoDBTable(tableName = "Alerts")
public final class Alert implements Serializable {
private static final long serialVersionUID = 4012517315640518044L;
#DynamoDBHashKey(attributeName = "AlertId") // Partition Key or Hash Attribute
private String alertId;
#DynamoDBTypeConvertedEnum
#DynamoDBAttribute(attributeName = "Source")
private Source type;
// Constructor(s), Getter(s), Setter(s), ToString, etc...
}
With the #DynamoDBTypeConvertedEnum annotation, the value that gets saved is BREACH, but I want breach.
{
"AlertId": { "S": "a083168d-cb23-4ec8-ab80-a1c16955c4b8" },
"Source": { "S": "BREACH" },
...
"CreatedAt": { "S": "2017-05-03T14:07:36.395Z" }
}
Any clues? I did try "converters" (not fully, I couldn't make it work though) but I think I have to end up doing one for each enum type since they are all different.
You can code the Alert class like this i.e. define the attribute as String and design the getter and setter to send/receive enum object (i.e. Source).
Alert class:-
#DynamoDBTable(tableName = "Alerts")
public final class Alert implements Serializable {
private static final long serialVersionUID = 4012517315640518044L;
private String alertId;
private String type;
#DynamoDBHashKey(attributeName = "AlertId")
public String getAlertId() {
return alertId;
}
#DynamoDBAttribute(attributeName = "Source")
public Source getType() {
if (type != null)
return Source.valueOf(type);
else
return null;
}
public void setAlertId(String alertId) {
this.alertId = alertId;
}
public void setType(Source type) {
this.type = type.desc();
}
}
Create Alert:-
Stores the value as expected on database table. The get item from DynamoDB table also works fine.
public Boolean createAlert(String alertId, Source source) {
DynamoDBMapper dynamoDBMapper = new DynamoDBMapper(dynamoDBClient);
Alert alert = new Alert();
alert.setAlertId(alertId);
alert.setType(source);
dynamoDBMapper.save(alert);
return true;
}
Override toString() this should work.
public enum Source {
BREACH("breach"),
LEAKAGE("leakage");
private final String desc;
Source(String desc) { this.desc = desc; }
public String desc() { return desc; }
#Override
public String toString() { return desc; }
}

I Can't Update table with ormlite android

The problem is that I have a table product and my update script doesn't work aparently. It allwas return false.
Product.class
#DatabaseTable(tableName = "Product")
public class Product {
#DatabaseField(index = true, generatedId = true)
private int productId;
#DatabaseField
private String name;
#DatabaseField
private int quantity;
//#DatabaseField(canBeNull = true)
//private Integer categorie;
//http://logic-explained.blogspot.com.ar/2011/12/using-ormlite-in-android-projects.html
#DatabaseField
private int categorie;
//#ForeignCollectionField
//private ForeignCollection<Categorie> itemsCategorie;
#DatabaseField
private String description;
#DatabaseField
private String photo;
Product() {
}
public Product(int productId, String name, int quantity, int categorie, String description, String photo) {
super();
this.productId = productId;
this.name = name;
this.quantity = quantity;
this.categorie = categorie;
this.description = description;
this.photo = photo;
}
public void setDescription(String description) {
this.description = description;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddress() {
return description;
}
public void setAddress(String address) {
this.description = address;
}
public int getProductId() {
return productId;
}
public void setProductId(int productId) {
this.productId = productId;
}
public int getQuantity() {
return quantity;
}
public void setQuantity(int quantity) {
this.quantity = quantity;
}
public int getCategorie() {
return categorie;
}
public void setCategorie(int categorie) {
this.categorie = categorie;
}
public String getPhoto() {
return photo;
}
public void setPhoto(String photo) {
this.photo = photo;
}
public CharSequence getDesc() {
return null;
}
}
my script updateProduct
public boolean updateProduct(Product p) {
boolean ret = false;
if (productDao != null) {
try {
productDao = getDao(Product.class);
UpdateBuilder<Product, Integer> updateBuilder = productDao
.updateBuilder();
updateBuilder.updateColumnValue("name", p.getName());
updateBuilder.updateColumnValue("quantity", p.getQuantity());
updateBuilder.updateColumnValue("categorie", p.getCategorie());
updateBuilder.updateColumnValue("description", p.getDesc());
updateBuilder.updateColumnValue("photo", p.getPhoto());
// but only update the rows where the description is some value
updateBuilder.where().eq("productId", p.getProductId());
// actually perform the update
String str = updateBuilder.prepareStatementString();
// UPDATE `Product` SET `name` = 'gcd' ,`quantity` = 1
// ,`categorie` = 1 ,`description` = ? ,`photo` = '' WHERE
// `productId` = 0
if (productDao.update(updateBuilder.prepare()) != 1) {
ret = false;
} else {
productDao.refresh(p);
ret = true;
}
} catch (Exception e) {
ret = false;
e.printStackTrace();
}
}
return ret;
}
then I call it with a function like this, but allways return false :(
public boolean updateProduct(Product p) {
boolean ret = false;
try {
ret = getHelper().updateProduct(p);
} catch (Exception e) {
e.printStackTrace();
ret =false;
}
return ret;
}
I can create and delete but I can not update . I tried everything.
If you please take a moment to answer my question I will appreciate.
for other developers, if you come face to face with a problem like this you should ensure the table must have an identity key.
#DatabaseTable(tableName = "User")
public class User {
#DatabaseField(generatedId = true)
public int id;
#DatabaseField
public String ServiceUserId;
#DatabaseField
public boolean IsActive;
#DatabaseField
public String FirstName;
#DatabaseField
public String LastName;
#DatabaseField
public String Key;
#DatabaseField
public String Email;
}
The solution was
Simply get the Instance of the object Product from the DB then modify to finaly send to the updateProduct method.
for example first I need to create any method first to get an objet by ID
// get the Instance calling to the getProductByID
Product p = getHelper().getProductByID(p.getId())
//modify any value of the product
p.setFirstName("asd");
//call the update
ret = getHelper().updateProduct(p);
then my objects is Updated.
Put attention for the object Id(should be the same) and use the natif function update(Product);
In your case, you must override equals and hashCode.

Categories

Resources