6

Trying to learn about Jackson some, so I'm writing a simple program that reads a file/creates one to store some JSON in it. From the Jackson website I figured out how to read and write from the file, but in the case of my rudimentary program, i'd like to append as well. I'm basically trying to store a list of shopping lists. There is a shopping list object which has store name, amd items for that store.

The trouble is that I cannot figure a way to append another entry to the end of the file (in JSON format). Here is what I am working with so far, you can ignore the first bit it's just a silly console scanner asking for input:

    public class JacksonExample {

    static ObjectMapper mapper = new ObjectMapper();
    static File file = new File("C:/Users/stephen.protzman/Desktop/user.json");
    static List<ShoppingList> master = new ArrayList<ShoppingList>();

    public static void main(String[] args) {

        Scanner in = new Scanner(System.in);
        boolean running = true;
        while (running) {
            System.out.println("[ 1 ] Add a new shopping list");
            System.out.println("[ 2 ] View all shopping lists");
            System.out.println("[ 3 ] Save all shopping lists");
            int choice = Integer.parseInt(in.nextLine());
            switch (choice) {
            case 1:
                getNewList();
            case 2:
                display();
            case 3:
                running = false;
            }
        }
        in.close();
    }

    public static void getNewList() {
        boolean more = true;
        String store, temp;
        List<String> items = new ArrayList<String>();
        Scanner s = new Scanner(System.in);
        System.out.println("Enter the store: ");
        store = s.nextLine();
        System.out.println("Enter each item [If done type 'DONE'] :");
        while (more) {

            temp = s.nextLine();
            if (temp != null) {
                if (temp.toUpperCase().equals("DONE")) {
                    more = false;
                } else {
                    items.add(temp);
                }
            }

        }
        save(store, items);
        s.close();

    }

    public static void display() {
        try {
            ShoppingList list = mapper.readValue(file, ShoppingList.class);
            System.out.println(mapper.defaultPrettyPrintingWriter()
                    .writeValueAsString(list));

        } catch (JsonParseException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (JsonMappingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    public static void save(String store, List<String> items) {
        //load in old one
        try {
            ShoppingList list = mapper.readValue(file, ShoppingList.class);
            System.out.println(mapper.defaultPrettyPrintingWriter()
                    .writeValueAsString(list));

        } catch (JsonParseException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (JsonMappingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        //add to end of older list
        ShoppingList tempList = new ShoppingList();
        tempList.setStore(store);
        tempList.setItems(items);

        master.add(tempList);

        try {

            mapper.writeValue(file, master);


        } catch (JsonGenerationException e) {

            e.printStackTrace();

        } catch (JsonMappingException e) {

            e.printStackTrace();

        } catch (IOException e) {

            e.printStackTrace();

        }
    }

}

I want to keep using ObjectMapper (considering im trying to learn Jackson) I just havent found a way to append yet is all. Any ideas?

erp
  • 2,950
  • 9
  • 45
  • 90

2 Answers2

6

To append content, you need to use Streaming API to create JsonGenerator; and then you can give this generator to ObjectMapper to write to. So something like:

JsonGenerator g = mapper.getFactory().createGenerator(outputStream);
mapper.writeValue(g, valueToWrite);
// and more
g.close();
StaxMan
  • 113,358
  • 34
  • 211
  • 239
  • I wonder why the ObjectMapper author never thought of providing an append method?! – C J Nov 13 '18 at 23:40
  • From API perspective there are better ways; mapper now has `ObectMapper.writeValues()` that returns thing designed for append. append() method just would not work well as far as API design goes. – StaxMan Nov 14 '18 at 23:33
5

Below method can be used to write objects into a json file in append mode. it first reads your existing json file and adds new java objects to JSON file.

public static void appendWriteToJson() {

    ObjectMapper mapper = new ObjectMapper();

    try {
        // Object to JSON in file
        JsonDaoImpl js = new JsonDaoImpl();
        URL resourceUrl = js.getClass().getResource("/data/actionbean.json");
        System.out.println(resourceUrl);
        File file = new File(resourceUrl.toURI());

        PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(file, true))); // append mode file writer

        mapper.writeValue(out, DummyBeanObject);

    } catch (Exception e) {
        e.printStackTrace();
    }
}
Lakshmikant Deshpande
  • 826
  • 1
  • 12
  • 30
Dean Jain
  • 1,959
  • 19
  • 15