1

SOLVED.

I have a question regarding the writing/reading list of objects with Gson. I have a Product class:

public class Product {
    private String name;
    private double price;
    private int quantity;
    public Product(String name, double price, int quantity) {
        this.name = name;
        this.price = price;
        this.quantity = quantity;
    }
......

Then I have a class for ProductList:

public class ProductMenu {
    public List<Product> productList;
    public ProductMenu() {
        productList = new ArrayList<>();
    }
......

I initialize my product list in another class:

public class ShoppingOperations {
    ProductUpdater import = new ProductUpdaterFromJson();
    private ProductMenu shopItems = import.importProducts();
.....

What I wanna do, to initialize my product list in the constructor, like this:

public class ProductMenu {
    public List<Product> productList;
    public ProductMenu() {
        ProductUpdater getList = new ProductUpdaterFromJson();
        productList = getList.importProducts();
    }
......

This is my method which writes to the .json file the list of objects:

public class ProductUpdaterFromJson implements ProductUpdater {
    public final static String PATH = "src\\shop\\products\\promenu.json5";
    @Override
    public void updateWarehouseData(ProductMenu shopItems) {
        Gson gson = new GsonBuilder().setPrettyPrinting().create();
        try {
            Writer writer = new FileWriter(PATH);
            gson.toJson(shopItems, writer);
            writer.flush();
            writer.close();
        } catch (IOException e) {
            System.out.println("file not found");
            e.printStackTrace();
        }
    }

And the .json file looks like that. It's generated with Gson:

{
  "productList": [
    {
      "name": "Cheese",
      "price": 1.37,
      "quantity": 6
    },
    {
      "name": "Milk",
      "price": 1.16,
      "quantity": 7
    },
    {
      "name": "Milka",
      "price": 0.66,
      "quantity": 2
    },
    {
      "name": "Potatoes",
      "price": 0.7,
      "quantity": 7
    },
    {
      "name": "Tea",
      "price": 2.1,
      "quantity": 4
    }
  ]
}

But I'm getting an error trying to read this file. The constructor expects List, but my file writer writes ProductMenu (it's the same list with products), but I have this error - Exception in thread "main" com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_ARRAY but was STRING at line 1 column 1 path $ And this is the method to read from .json file:

public final static String PATH = "src\\shop\\products\\promenu.json5";
public List<Product> importProducts2() {
    Gson gson = new Gson();
    Type userListType = new TypeToken<ArrayList<Product>>(){}.getType();
    return gson.fromJson(PATH, userListType);
}

How can I solve this problem. Writer writes , but impossible to read the file and initialize list with products.

The solution I found with help of members:

public class ProductUpdaterFromJson implements ProductUpdater {
    public final static String PATH = "src\\shop\\products\\promenu.json5";

    @Override
    public void updateWarehouseData(ProductMenu shopItems) {
        Gson gson = new GsonBuilder().setPrettyPrinting().create();
        try {
            Writer writer = new FileWriter(PATH);
            gson.toJson(shopItems.productList, writer);
            writer.flush();
            writer.close();
        } catch (IOException e) {
            System.out.println("file not found");
            e.printStackTrace();
        }
    }

    public List<Product> importProducts() {
        Gson gson = new Gson();
        List<Product> list = null;
        try {
            Reader reader = new FileReader(PATH);
            Type userListType = new TypeToken<ArrayList<Product>>(){}.getType();
            list =  gson.fromJson(reader, userListType);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        return list;
    }
}

And the constructor:

public class ProductMenu {

    public List<Product> productList;

    public ProductMenu() {
        ProductUpdater listFromJson = new ProductUpdaterFromJson();
        productList = listFromJson.importProducts();
    }
andrulis
  • 9
  • 1
  • 4
  • 2
    You parse the string `src\\shop\\products\\promenu.json5` not the content of the file – Jens May 05 '20 at 14:21
  • As @Jens already mentioned, at `gson.fromJson(PATH, userListType);` `PATH` is a string holding representing path, not content of file from that path. Please see [how to parse JSON file with GSON](https://stackoverflow.com/q/29965764) – Pshemo May 05 '20 at 14:26
  • @Jens Thank You, I changed that to: `public List importProducts2() { Gson gson = new Gson(); List im = null; try { Reader reader = new FileReader(PATH); Type userListType = new TypeToken>(){}.getType(); im = gson.fromJson(reader, userListType); } catch (FileNotFoundException e) { e.printStackTrace(); } return im; }` Now te problem is: Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 2 path $ – andrulis May 05 '20 at 14:32
  • you write an object (ProductMenu) and want to read a list (ArrayList) – Marc Stroebel May 05 '20 at 14:35
  • I made a change, as recommended to save as plain list of products: `public void updateWarehouseData(ProductMenu shopItems) { Gson gson = new GsonBuilder().setPrettyPrinting().create(); try { Writer writer = new FileWriter(PATH); gson.toJson(shopItems.productList, writer); writer.flush(); writer.close(); } catch (IOException e) { System.out.println("file not found"); e.printStackTrace(); } }` – andrulis May 05 '20 at 14:47
  • @andrulis i guess your path is wrong. Use .class.getResourceAsStream(..) and remove the `src` in front of the path. Use a debugger to see what is happening. – Jens May 05 '20 at 14:47
  • @Jens With help I found solution. Added to the original post at the end. Now everything works fine, Thanks for help. – andrulis May 05 '20 at 15:17

1 Answers1

0

try using ProductMenu as in serialization

public List<Product> importProducts2() {
    Gson gson = new Gson();
    ProductMenu productMenu = gson.fromJson(new InputStreamReader(...), ProductMenu.class);
    return productMenu.productList
}

Or serialize the plain list

gson.toJson(shopItems.productList, writer);
Marc Stroebel
  • 2,295
  • 1
  • 12
  • 21
  • It shows: _Exception in thread "main" java.lang.NullPointerException_ – andrulis May 05 '20 at 14:37
  • I serialized the plain list like you wrote. The json file looks ok. But still error trying to read. – andrulis May 05 '20 at 14:44
  • Yes. Null pointer. I use same path to write the .json file, and it works. – andrulis May 05 '20 at 14:49
  • _Exception in thread "main" java.lang.NullPointerException at java.base/java.io.Reader.(Reader.java:167) at java.base/java.io.InputStreamReader.(InputStreamReader.java:72) at shop.products.ProductUpdaterFromJson.importProducts2(ProductUpdaterFromJson.java:42)_ I'm using your suggested code now: _ProductMenu productMenu = gson.fromJson(new InputStreamReader(getClass().getResourceAsStream(PATH)), ProductMenu.class);_ – andrulis May 05 '20 at 14:52
  • Try `gson.fromJson(new FileReader(PATH), ProductMenu.class);` Using getResourceAsStream needs a different path format – Marc Stroebel May 05 '20 at 14:56
  • @MarcStröbel Thank You for help, found a final solution that works. I will edit post and add the final working version. – andrulis May 05 '20 at 15:10