4

How to use the stream API json with jackson? See my code below:

    ObjectMapper mapper = new ObjectMapper();

    Map<String, Object> map = new HashMap<String, Object>();

    List<Object> list = new ArrayList<Object>();

    // Get images in database
    try {
            Class.forName(DRIVER);
            connection = DriverManager.getConnection(URL, USER, PASSWORD);

            Statement s = connection.createStatement();
            ResultSet r = s.executeQuery("select * from images");

            while (r.next()) {

                byte[] imageBytes = r.getBytes("image");
                String imageBase64 = DatatypeConverter.printBase64Binary(imageBytes);
                list.add(imageBase64);
            }

    } catch (SQLException e) {

    }

    map.put("images", list);

    // Stream Json API
    try {
            mapper.writeValue(new File("c:\\images.json"), map);
    } catch (JsonGenerationException e) {
            e.printStackTrace();
    } catch (JsonMappingException e) {
            e.printStackTrace();
    } catch (IOException e) {
            e.printStackTrace();
    }

Always return out of memory. I dont know to use stream with jackson. I working with extra large json, average 2000 images, to each image a imageBase64. what am I doing wrong?

Schlacter James
  • 147
  • 1
  • 3
  • 9

1 Answers1

1

Instead of keeping all images in memory, just read and write them incrementally. An example of Jackson Streaming API can be found here ("Reading and Writing Event Streams").

EDIT: This should be too hard to figure out folks... but here's a skeletal example:

// typed from memory, some methods may be off a bit
JsonFactory f = objectMapper.getFactory();
JsonGenerator gen = f.createGenerator(new File("c:\\images.json"));
gen.writeStartArray(); // to get array of objects
// get the DB connection etc
while (r.next()) {
  gen.writeFieldName("image");
  InputStream in = r.getBinaryStream("image");
  gen.writeBinary(in, -1); // length optional for JSON
  in.close();
}

    gen.writeEndArray(); // to get array of objects gen.close();

and that should about do the trick.

StaxMan
  • 113,358
  • 34
  • 211
  • 239
  • The same problem. Cannot use the base64 to generate json because the file is huge. No Way. How can I generate a url for each image from database? Any idea? – Schlacter James Feb 27 '13 at 13:52
  • Same what? When you read and write things incrementally, they are NOT stored in memory -- you obviously write to a File or other streamable storage. And instead of encoding Base64 in memory, that too can be written incrementally, as long as binary data is accessible using `InputStream`. As to URL, well, that's another question and outside scope of JSON data-binding. But really, instead of asking questions you should try to understand the example I pointed, and see _why_ it makes a difference. – StaxMan Feb 27 '13 at 17:58
  • thank you, I can generate images.json, no problem, but to read images.json is impossible, huge files. No way for mobile application with limited resources. Now, generate a URL to each image, solve my problem. – Schlacter James Feb 27 '13 at 21:35
  • Why would reading be a problem? Use streaming API as well, to read data reverse of writing, using `JsonParser`. I'll let you figure that one out. – StaxMan Feb 27 '13 at 22:27