• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

nats-io / json.java / #51

20 Jun 2025 03:37PM UTC coverage: 97.139% (-2.4%) from 99.519%
#51

push

github

web-flow
Merge pull request #18 from nats-io/revert

Revert back to Java 8 version

296 of 309 new or added lines in 5 files covered. (95.79%)

5 existing lines in 3 files now uncovered.

747 of 769 relevant lines covered (97.14%)

0.97 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

93.38
/src/main/java/io/nats/json/JsonValueUtils.java
1
// Copyright 2023-2024 The NATS Authors
2
// Licensed under the Apache License, Version 2.0 (the "License");
3
// you may not use this file except in compliance with the License.
4
// You may obtain a copy of the License at:
5
//
6
// http://www.apache.org/licenses/LICENSE-2.0
7
//
8
// Unless required by applicable law or agreed to in writing, software
9
// distributed under the License is distributed on an "AS IS" BASIS,
10
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
// See the License for the specific language governing permissions and
12
// limitations under the License.
13

14
package io.nats.json;
15

16
import java.math.BigDecimal;
17
import java.math.BigInteger;
18
import java.nio.charset.StandardCharsets;
19
import java.time.Duration;
20
import java.time.ZonedDateTime;
21
import java.util.*;
22
import java.util.function.Function;
23

24
import static io.nats.json.JsonValue.*;
25

26
/**
27
 * Internal json value helpers.
28
 */
29
public abstract class JsonValueUtils {
30

31
    private JsonValueUtils() {} /* ensures cannot be constructed */
32

33
    public interface JsonValueSupplier<T> {
34
        T get(JsonValue v);
35
    }
36

37
    public static <T> T read(JsonValue jsonValue, String key, JsonValueSupplier<T> valueSupplier) {
38
        JsonValue v = jsonValue == null || jsonValue.map == null ? null : jsonValue.map.get(key);
1✔
39
        return valueSupplier.get(v);
1✔
40
    }
41

42
    public static JsonValue readValue(JsonValue jsonValue, String key) {
43
        return read(jsonValue, key, v -> v);
1✔
44
    }
45

46
    public static JsonValue readObject(JsonValue jsonValue, String key) {
47
        return read(jsonValue, key, v -> v == null ? EMPTY_MAP : v);
1✔
48
    }
49

50
    public static List<JsonValue> readArray(JsonValue jsonValue, String key) {
NEW
51
        return read(jsonValue, key, v -> v == null ? EMPTY_ARRAY.array : v.array);
×
52
    }
53

54
    public static Map<String, String> readStringStringMap(JsonValue jv, String key) {
55
        JsonValue o = readObject(jv, key);
1✔
56
        if (o.type == Type.MAP && !o.map.isEmpty()) {
1✔
57
            Map<String, String> temp = new HashMap<>();
1✔
58
            for (String k : o.map.keySet()) {
1✔
59
                String value = readString(o, k);
1✔
60
                if (value != null) {
1✔
61
                    temp.put(k, value);
1✔
62
                }
63
            }
1✔
64
            return temp.isEmpty() ? null : temp;
1✔
65
        }
66
        return null;
1✔
67
    }
68

69
    public static String readString(JsonValue jsonValue, String key) {
70
        return read(jsonValue, key, v -> v == null ? null : v.string);
1✔
71
    }
72

73
    public static String readString(JsonValue jsonValue, String key, String dflt) {
74
        return read(jsonValue, key, v -> v == null ? dflt : v.string);
1✔
75
    }
76

77
    public static ZonedDateTime readDate(JsonValue jsonValue, String key) {
78
        return read(jsonValue, key,
1✔
79
            v -> v == null || v.string == null ? null : DateTimeUtils.parseDateTimeThrowParseError(v.string));
1✔
80
    }
81

82
    public static Integer readInteger(JsonValue jsonValue, String key) {
83
        return read(jsonValue, key, v -> v == null ? null : getInteger(v));
1✔
84
    }
85

86
    public static int readInteger(JsonValue jsonValue, String key, int dflt) {
87
        return read(jsonValue, key, v -> {
1✔
88
            if (v != null) {
1✔
89
                Integer i = getInteger(v);
1✔
90
                if (i != null) {
1✔
91
                    return i;
1✔
92
                }
93
            }
94
            return dflt;
1✔
95
        });
96
    }
97

98
    public static Long readLong(JsonValue jsonValue, String key) {
99
        return read(jsonValue, key, v -> v == null ? null : getLong(v));
1✔
100
    }
101

102
    public static long readLong(JsonValue jsonValue, String key, long dflt) {
103
        return read(jsonValue, key, v -> {
1✔
104
            if (v != null) {
1✔
105
                Long l = getLong(v);
1✔
106
                if (l != null) {
1✔
107
                    return l;
1✔
108
                }
109
            }
110
            return dflt;
1✔
111
        });
112
    }
113

114
    public static boolean readBoolean(JsonValue jsonValue, String key) {
115
        return readBoolean(jsonValue, key, false);
1✔
116
    }
117

118
    public static Boolean readBoolean(JsonValue jsonValue, String key, Boolean dflt) {
119
        return read(jsonValue, key,
1✔
120
            v -> v == null || v.bool == null ? dflt : v.bool);
1✔
121
    }
122

123
    public static Duration readNanos(JsonValue jsonValue, String key) {
124
        Long l = readLong(jsonValue, key);
1✔
125
        return l == null ? null : Duration.ofNanos(l);
1✔
126
    }
127

128
    public static Duration readNanos(JsonValue jsonValue, String key, Duration dflt) {
129
        Long l = readLong(jsonValue, key);
1✔
130
        return l == null ? dflt : Duration.ofNanos(l);
1✔
131
    }
132

133
    public static <T> List<T> listOf(JsonValue v, Function<JsonValue, T> provider) {
134
        List<T> list = new ArrayList<>();
1✔
135
        if (v != null && v.array != null) {
1✔
136
            for (JsonValue jv : v.array) {
1✔
137
                T t = provider.apply(jv);
1✔
138
                if (t != null) {
1✔
139
                    list.add(t);
1✔
140
                }
141
            }
1✔
142
        }
143
        return list;
1✔
144
    }
145

146
    public static <T> List<T> optionalListOf(JsonValue v, Function<JsonValue, T> provider) {
147
        List<T> list = listOf(v, provider);
1✔
148
        return list.isEmpty() ? null : list;
1✔
149
    }
150

151
    public static List<String> readStringList(JsonValue jsonValue, String key) {
152
        return read(jsonValue, key, v -> listOf(v, jv -> jv.string));
1✔
153
    }
154

155
    public static List<String> readStringListIgnoreEmpty(JsonValue jsonValue, String key) {
156
        return read(jsonValue, key, v -> listOf(v, jv -> {
1✔
157
            if (jv.string != null) {
1✔
158
                String s = jv.string.trim();
1✔
159
                if (!s.isEmpty()) {
1✔
160
                    return s;
1✔
161
                }
162
            }
163
            return null;
1✔
164
        }));
165
    }
166

167
    public static List<String> readOptionalStringList(JsonValue jsonValue, String key) {
168
        return read(jsonValue, key, v -> optionalListOf(v, jv -> jv.string));
1✔
169
    }
170

171
    public static List<Long> readLongList(JsonValue jsonValue, String key) {
NEW
172
        return read(jsonValue, key, v -> listOf(v, JsonValueUtils::getLong));
×
173
    }
174

175
    public static List<Duration> readNanosList(JsonValue jsonValue, String key) {
176
        return readNanosList(jsonValue, key, false);
1✔
177
    }
178

179
    public static List<Duration> readNanosList(JsonValue jsonValue, String key, boolean nullIfEmpty) {
180
        List<Duration> list = read(jsonValue, key,
1✔
181
            v -> listOf(v, vv -> {
1✔
182
                Long l = getLong(vv);
1✔
183
                return l == null ? null : Duration.ofNanos(l);
1✔
184
            })
185
        );
186
        return list.isEmpty() && nullIfEmpty ? null : list;
1✔
187
    }
188

189
    public static byte[] readBytes(JsonValue jsonValue, String key) {
190
        String s = readString(jsonValue, key);
1✔
191
        return s == null ? null : s.getBytes(StandardCharsets.US_ASCII);
1✔
192
    }
193

194
    public static byte[] readBase64(JsonValue jsonValue, String key) {
NEW
195
        String b64 = readString(jsonValue, key);
×
NEW
196
        return b64 == null ? null : Base64.getDecoder().decode(b64);
×
197
    }
198

199
    public static Integer getInteger(JsonValue v) {
200
        if (v.i != null) {
1✔
201
            return v.i;
1✔
202
        }
203
        // just in case the number was stored as a long, which is unlikely, but I want to handle it
204
        if (v.l != null && v.l <= Integer.MAX_VALUE && v.l >= Integer.MIN_VALUE) {
1✔
205
            return v.l.intValue();
1✔
206
        }
207
        return null;
1✔
208
    }
209

210
    public static Long getLong(JsonValue v) {
211
        return v.l != null ? v.l : (v.i != null ? (long)v.i : null);
1✔
212
    }
213

214
    public static long getLong(JsonValue v, long dflt) {
215
        return v.l != null ? v.l : (v.i != null ? (long)v.i : dflt);
1✔
216
    }
217

218
    public static JsonValue instance(Duration d) {
219
        return new JsonValue(d.toNanos());
1✔
220
    }
221

222
    @SuppressWarnings("rawtypes")
223
    public static JsonValue instance(Collection list) {
224
        JsonValue v = new JsonValue(new ArrayList<>());
1✔
225
        for (Object o : list) {
1✔
226
            v.array.add(toJsonValue(o));
1✔
227
        }
1✔
228
        return v;
1✔
229
    }
230

231
    @SuppressWarnings("rawtypes")
232
    public static JsonValue instance(Map map) {
233
        JsonValue v = new JsonValue(new HashMap<>());
1✔
234
        for (Object key : map.keySet()) {
1✔
235
            v.map.put(key.toString(), toJsonValue(map.get(key)));
1✔
236
        }
1✔
237
        return v;
1✔
238
    }
239

240
    public static JsonValue toJsonValue(Object o) {
241
        if (o == null) {
1✔
242
            return JsonValue.NULL;
1✔
243
        }
244
        if (o instanceof JsonValue) {
1✔
245
            return (JsonValue)o;
1✔
246
        }
247
        if (o instanceof JsonSerializable) {
1✔
248
            return ((JsonSerializable)o).toJsonValue();
1✔
249
        }
250
        if (o instanceof Map) {
1✔
251
            //noinspection unchecked,rawtypes
252
            return new JsonValue((Map)o);
1✔
253
        }
254
        if (o instanceof List) {
1✔
255
            //noinspection unchecked,rawtypes
256
            return new JsonValue((List)o);
1✔
257
        }
258
        if (o instanceof Set) {
1✔
259
            //noinspection unchecked,rawtypes
260
            return new JsonValue(new ArrayList<>((Set)o));
1✔
261
        }
262
        if (o instanceof String) {
1✔
263
            String s = ((String)o).trim();
1✔
264
            return s.length() == 0 ? new JsonValue() : new JsonValue(s);
1✔
265
        }
266
        if (o instanceof Boolean) {
1✔
267
            return new JsonValue((Boolean)o);
1✔
268
        }
269
        if (o instanceof Integer) {
1✔
270
            return new JsonValue((Integer)o);
1✔
271
        }
272
        if (o instanceof Long) {
1✔
273
            return new JsonValue((Long)o);
1✔
274
        }
275
        if (o instanceof Double) {
1✔
276
            return new JsonValue((Double)o);
1✔
277
        }
278
        if (o instanceof Float) {
1✔
279
            return new JsonValue((Float)o);
1✔
280
        }
281
        if (o instanceof BigDecimal) {
1✔
282
            return new JsonValue((BigDecimal)o);
1✔
283
        }
284
        if (o instanceof BigInteger) {
1✔
285
            return new JsonValue((BigInteger)o);
1✔
286
        }
287
        return new JsonValue(o.toString());
1✔
288
    }
289

290
    public static MapBuilder mapBuilder() {
291
        return new MapBuilder();
1✔
292
    }
293

294
    public static class MapBuilder implements JsonSerializable {
295
        public JsonValue jv;
296

297
        public MapBuilder() {
1✔
298
            jv = new JsonValue(new HashMap<>());
1✔
299
        }
1✔
300

NEW
301
        public MapBuilder(JsonValue jv) {
×
NEW
302
            this.jv = jv;
×
NEW
303
        }
×
304

305
        public MapBuilder put(String s, Object o) {
306
            if (o != null) {
1✔
307
                JsonValue vv = JsonValueUtils.toJsonValue(o);
1✔
308
                if (vv.type != JsonValue.Type.NULL) {
1✔
309
                    jv.map.put(s, vv);
1✔
310
                    jv.mapOrder.add(s);
1✔
311
                }
312
            }
313
            return this;
1✔
314
        }
315

316
        public MapBuilder put(String s, Map<String, String> stringMap) {
317
            if (stringMap != null) {
1✔
318
                MapBuilder mb = new MapBuilder();
1✔
319
                for (String key : stringMap.keySet()) {
1✔
NEW
320
                    mb.put(key, stringMap.get(key));
×
NEW
321
                }
×
322
                jv.map.put(s, mb.jv);
1✔
323
                jv.mapOrder.add(s);
1✔
324
            }
325
            return this;
1✔
326
        }
327

328
        @Override
329
        public String toJson() {
330
            return jv.toJson();
1✔
331
        }
332

333
        @Override
334
        public JsonValue toJsonValue() {
335
            return jv;
1✔
336
        }
337
    }
338

339
    public static ArrayBuilder arrayBuilder() {
340
        return new ArrayBuilder();
1✔
341
    }
342

343
    public static class ArrayBuilder implements JsonSerializable {
1✔
344
        public JsonValue jv = new JsonValue(new ArrayList<>());
1✔
345
        public ArrayBuilder add(Object o) {
346
            if (o != null) {
1✔
347
                JsonValue vv = JsonValueUtils.toJsonValue(o);
1✔
348
                if (vv.type != JsonValue.Type.NULL) {
1✔
349
                    jv.array.add(JsonValueUtils.toJsonValue(o));
1✔
350
                }
351
            }
352
            return this;
1✔
353
        }
354

355
        @Override
356
        public String toJson() {
357
            return jv.toJson();
1✔
358
        }
359

360
        @Override
361
        public JsonValue toJsonValue() {
362
            return jv;
1✔
363
        }
364

365
        @Deprecated
366
        public JsonValue getJsonValue() {
NEW
367
            return jv;
×
368
        }
369
    }
370
}
371

STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc