001package io.avaje.jsonb.stream; 002 003import io.avaje.jsonb.JsonReader; 004import io.avaje.jsonb.JsonWriter; 005import io.avaje.jsonb.spi.*; 006 007import java.io.*; 008import java.nio.charset.StandardCharsets; 009 010/** 011 * Default implementation of JsonStreamAdapter provided with Jsonb. 012 */ 013public final class JsonStream implements JsonStreamAdapter { 014 015 /** 016 * Used to build JsonStream with custom settings. 017 */ 018 public static final class Builder { 019 020 private boolean serializeNulls; 021 private boolean serializeEmpty; 022 private boolean failOnUnknown; 023 024 /** 025 * Set to true to serialize nulls. Defaults to false. 026 */ 027 public Builder serializeNulls(boolean serializeNulls) { 028 this.serializeNulls = serializeNulls; 029 return this; 030 } 031 032 /** 033 * Set to true to serialize empty collections. Defaults to false. 034 */ 035 public Builder serializeEmpty(boolean serializeEmpty) { 036 this.serializeEmpty = serializeEmpty; 037 return this; 038 } 039 040 /** 041 * Set to true to fail on unknown properties. Defaults to false. 042 */ 043 public Builder failOnUnknown(boolean failOnUnknown) { 044 this.failOnUnknown = failOnUnknown; 045 return this; 046 } 047 048 /** 049 * Build and return the JsonStream. 050 */ 051 public JsonStream build() { 052 return new JsonStream(serializeNulls, serializeEmpty, failOnUnknown); 053 } 054 } 055 056 private final boolean serializeNulls; 057 private final boolean serializeEmpty; 058 private final boolean failOnUnknown; 059 060 /** 061 * Create with the given default configuration. 062 */ 063 public JsonStream() { 064 this(false, false, false); 065 } 066 067 /** 068 * Create additionally providing the jsonFactory. 069 */ 070 public JsonStream(boolean serializeNulls, boolean serializeEmpty, boolean failOnUnknown) { 071 this.serializeNulls = serializeNulls; 072 this.serializeEmpty = serializeEmpty; 073 this.failOnUnknown = failOnUnknown; 074 } 075 076 /** 077 * Return a new builder to create a JsonStream with custom configuration. 078 * 079 * <pre>{@code 080 * 081 * var jsonStream = JsonStream.newBuilder() 082 * .serializeNulls(true) 083 * .build(); 084 * 085 * }</pre> 086 */ 087 public static Builder newBuilder() { 088 return new Builder(); 089 } 090 091 @Override 092 public PropertyNames properties(String... names) { 093 return JsonNames.of(names); 094 } 095 096 @Override 097 public JsonReader reader(String json) { 098 return reader(json.getBytes(StandardCharsets.UTF_8)); 099 } 100 101 @Override 102 public JsonReader reader(byte[] json) { 103 JsonParser parser = Recycle.parser(json); 104 return new JsonReadAdapter(parser, failOnUnknown); 105 } 106 107 @Override 108 public JsonReader reader(Reader reader) { 109 // TODO: Could recycle encoder and buffer 110 return reader(new ReaderInputStream(reader, StandardCharsets.UTF_8)); 111 } 112 113 @Override 114 public JsonReader reader(InputStream inputStream) { 115 try { 116 JsonParser parser = Recycle.parser(inputStream); 117 return new JsonReadAdapter(parser, failOnUnknown); 118 } catch (IOException e) { 119 throw new UncheckedIOException(e); 120 } 121 } 122 123 @Override 124 public JsonWriter writer(Writer writer) { 125 // TODO: Could recycle buffer used 126 return writer(new WriterOutputStream(writer, StandardCharsets.UTF_8)); 127 } 128 129 @Override 130 public JsonWriter writer(OutputStream outputStream) { 131 return wrap(gen(outputStream)); 132 } 133 134 @Override 135 public BufferedJsonWriter bufferedWriter() { 136 JsonGenerator generator = Recycle.generator(); 137 return new BufferedWriter(wrap(generator), generator); 138 } 139 140 @Override 141 public BytesJsonWriter bufferedWriterAsBytes() { 142 JsonGenerator generator = Recycle.generator(); 143 return new BytesWriter(wrap(generator), generator); 144 } 145 146 private JsonGenerator gen(OutputStream outputStream) { 147 return Recycle.generator(outputStream); 148 } 149 150 private JsonWriteAdapter wrap(JsonGenerator generator) { 151 return new JsonWriteAdapter(generator, serializeNulls, serializeEmpty); 152 } 153 154 private static class BufferedWriter extends DelegateJsonWriter implements BufferedJsonWriter { 155 156 private final JsonGenerator generator; 157 158 BufferedWriter(JsonWriteAdapter delegate, JsonGenerator generator) { 159 super(delegate); 160 this.generator = generator; 161 } 162 163 @Override 164 public String result() { 165 return generator.toString(); 166 } 167 } 168 169 private static class BytesWriter extends DelegateJsonWriter implements BytesJsonWriter { 170 171 private final JsonGenerator generator; 172 173 public BytesWriter(JsonWriteAdapter delegate, JsonGenerator generator) { 174 super(delegate); 175 this.generator = generator; 176 } 177 178 @Override 179 public byte[] result() { 180 return generator.toByteArray(); 181 } 182 } 183}