2016-06-23 2 views
2

У меня есть поток строк. Каждая строка представляет собой объект JSON, как это, например:java поток разделен запятой

// {"foo": "bar", "bar": "foo"} 
String s1 = "{\"foo\": \"bar\", \"bar\": \"foo\"}"; 

Я получаю большое количество данных из базы данных, поэтому я использую Stream. И я хочу передать эти данные в вывод для ответа HTTP.

try (Stream<String> data = service.streamData()) { 
      os.write("[".getBytes()); 
      eventStream.forEach(s -> { 
         try { 
          os.write(s.getBytes()); 
          os.write(",".getBytes()); 
          os.write("\n".getBytes()); 
         } catch (IOException e) { 
          logger.error(e.getMessage()); 
         } 
        }); 
     } 
     os.write("{}]".getBytes()); 
     os.flush(); 

Поскольку каждая строка представляет объект json, я хочу вернуть массив этих объектов. В этом случае я должен вручную добавить "[" и "]" и разделить каждый элемент в потоке с помощью запятой. Но в итоге у меня будет запятая после последнего элемента. И это не будет действительным json.

Было бы выглядеть следующим образом:

["{"foo": "bar", "bar": "foo"}", "{"foo": "bar1", "bar": "foo1"}",] 

Любые идеи, как избавиться от последней запятой, используя поток?

+0

Хромого (но общий) подход был бы не выводить запятую после каждого сообщения, но выводить его перед каждым сообщением (за исключением первого, которое может обрабатываться логическим). – Thilo

+0

Другим хромым (но общим) подходом было бы просто добавить фиктивную запись (предполагается, что вы можете заставить клиентский код игнорировать его). – Thilo

+0

Thilo, спасибо за ваш ответ, мне нравится ваше первое предложение, не могли бы вы рассказать мне, как я могу проверить, является ли элемент первым, когда я использую для каждого в потоке? – user3127896

ответ

2

Обратите внимание, что, хотя выражение лямбда является аккуратной функцией, анонимные внутренние классы не перестают существовать. В случае, если вам нужен пользователь с естественным состоянием, они являются правильным инструментом. Вам даже не нужно условные здесь:

stream.forEach(new Consumer<String>() { 
    int header = '['; 
    public void accept(String string) { 
     try { 
      os.write(header); 
      os.write('\n'); 
      os.write(string.getBytes(StandardCharsets.UTF_8)); 
      header=','; 
     } catch (IOException e) { 
      logger.error(e.getMessage()); 
     } 
    } 
}); 
os.write('\n'); 
os.write(']'); 

В случае, если вы должны обрабатывать пустые потоки, вы можете расширить его

os.write('['); 
stream.forEach(new Consumer<String>() { 
    int header = ' '; 
    public void accept(String string) { 
     try { 
      os.write(header); 
      os.write('\n'); 
      os.write(string.getBytes(StandardCharsets.UTF_8)); 
      header=','; 
     } catch (IOException e) { 
      //logger.error(e.getMessage()); 
     } 
    } 
}); 
os.write('\n'); 
os.write(']'); 
Смежные вопросы