Статьи

Джерси / Джекс РС: потоковое JSON

Около года назад я написал сообщение в блоге, показывающее, как передавать HTTP-ответ с использованием Jersey / Jax RS, и недавно я хотел сделать то же самое, но на этот раз с использованием JSON.

Обычный шаблон — взять наш Java-объект и получить строковое представление JSON, но это не самое эффективное использование памяти, потому что теперь у нас есть Java-объект и строковое представление.

Это особенно проблематично, если нам нужно вернуть много данных в ответ.

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

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
@Path("/resource")
public class MadeUpResource
{
    private final ObjectMapper objectMapper;
  
    public MadeUpResource() {
        objectMapper = new ObjectMapper();
    }
  
    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public Response loadHierarchy(@PathParam( "pkPerson" ) String pkPerson) {
        final Map<Integer, String> people  = new HashMap<>();
        people.put(1, "Michael");
        people.put(2, "Mark");
  
        StreamingOutput stream = new StreamingOutput() {
            @Override
            public void write(OutputStream os) throws IOException, WebApplicationException
            {
                JsonGenerator jg = objectMapper.getJsonFactory().createJsonGenerator( os, JsonEncoding.UTF8 );
                jg.writeStartArray();
  
                for ( Map.Entry<Integer, String> person : people.entrySet()  )
                {
                    jg.writeStartObject();
                    jg.writeFieldName( "id" );
                    jg.writeString( person.getKey().toString() );
                    jg.writeFieldName( "name" );
                    jg.writeString( person.getValue() );
                    jg.writeEndObject();
                }
                jg.writeEndArray();
  
                jg.flush();
                jg.close();
            }
        };
  
  
        return Response.ok().entity( stream ).type( MediaType.APPLICATION_JSON ).build()    ;
    }
}

Если мы запустим это, мы увидим вывод:

1
[{"id":"1","name":"Michael"},{"id":"2","name":"Mark"}]

Это простой пример, но, надеюсь, легко увидеть, как мы могли бы это перевести, если бы мы хотели передавать более сложные данные.

Ссылка: Jersey / Jax RS: потоковое JSON от нашего партнера JCG Марка Нидхэма в блоге Марка Нидхэма