1 //===--- JSON.h - JSON values, parsing and serialization -------*- C++ -*-===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===---------------------------------------------------------------------===//
10 /// This file supports working with JSON data.
14 /// - classes which hold dynamically-typed parsed JSON structures
15 /// These are value types that can be composed, inspected, and modified.
16 /// See json::Value, and the related types json::Object and json::Array.
18 /// - functions to parse JSON text into Values, and to serialize Values to text.
19 /// See parse(), operator<<, and format_provider.
21 /// - a convention and helpers for mapping between json::Value and user-defined
22 /// types. See fromJSON(), ObjectMapper, and the class comment on Value.
24 /// Typically, JSON data would be read from an external source, parsed into
25 /// a Value, and then converted into some native data structure before doing
26 /// real work on it. (And vice versa when writing).
28 /// Other serialization mechanisms you may consider:
30 /// - YAML is also text-based, and more human-readable than JSON. It's a more
31 /// complex format and data model, and YAML parsers aren't ubiquitous.
32 /// YAMLParser.h is a streaming parser suitable for parsing large documents
33 /// (including JSON, as YAML is a superset). It can be awkward to use
34 /// directly. YAML I/O (YAMLTraits.h) provides data mapping that is more
35 /// declarative than the toJSON/fromJSON conventions here.
37 /// - LLVM bitstream is a space- and CPU- efficient binary format. Typically it
38 /// encodes LLVM IR ("bitcode"), but it can be a container for other data.
39 /// Low-level reader/writer libraries are in Bitcode/Bitstream*.h
41 //===---------------------------------------------------------------------===//
43 #ifndef LLVM_SUPPORT_JSON_H
44 #define LLVM_SUPPORT_JSON_H
46 #include "llvm/ADT/DenseMap.h"
47 #include "llvm/ADT/SmallVector.h"
48 #include "llvm/ADT/StringRef.h"
49 #include "llvm/Support/Error.h"
50 #include "llvm/Support/FormatVariadic.h"
51 #include "llvm/Support/raw_ostream.h"
57 // === String encodings ===
59 // JSON strings are character sequences (not byte sequences like std::string).
60 // We need to know the encoding, and for simplicity only support UTF-8.
62 // - When parsing, invalid UTF-8 is a syntax error like any other
64 // - When creating Values from strings, callers must ensure they are UTF-8.
65 // with asserts on, invalid UTF-8 will crash the program
66 // with asserts off, we'll substitute the replacement character (U+FFFD)
67 // Callers can use json::isUTF8() and json::fixUTF8() for validation.
69 // - When retrieving strings from Values (e.g. asString()), the result will
70 // always be valid UTF-8.
72 /// Returns true if \p S is valid UTF-8, which is required for use as JSON.
73 /// If it returns false, \p Offset is set to a byte offset near the first error.
74 bool isUTF8(llvm::StringRef S
, size_t *ErrOffset
= nullptr);
75 /// Replaces invalid UTF-8 sequences in \p S with the replacement character
76 /// (U+FFFD). The returned string is valid UTF-8.
77 /// This is much slower than isUTF8, so test that first.
78 std::string
fixUTF8(llvm::StringRef S
);
83 template <typename T
> Value
toJSON(const llvm::Optional
<T
> &Opt
);
85 /// An Object is a JSON object, which maps strings to heterogenous JSON values.
86 /// It simulates DenseMap<ObjectKey, Value>. ObjectKey is a maybe-owned string.
88 using Storage
= DenseMap
<ObjectKey
, Value
, llvm::DenseMapInfo
<StringRef
>>;
92 using key_type
= ObjectKey
;
93 using mapped_type
= Value
;
94 using value_type
= Storage::value_type
;
95 using iterator
= Storage::iterator
;
96 using const_iterator
= Storage::const_iterator
;
98 explicit Object() = default;
99 // KV is a trivial key-value struct for list-initialization.
100 // (using std::pair forces extra copies).
102 explicit Object(std::initializer_list
<KV
> Properties
);
104 iterator
begin() { return M
.begin(); }
105 const_iterator
begin() const { return M
.begin(); }
106 iterator
end() { return M
.end(); }
107 const_iterator
end() const { return M
.end(); }
109 bool empty() const { return M
.empty(); }
110 size_t size() const { return M
.size(); }
112 void clear() { M
.clear(); }
113 std::pair
<iterator
, bool> insert(KV E
);
114 template <typename
... Ts
>
115 std::pair
<iterator
, bool> try_emplace(const ObjectKey
&K
, Ts
&&... Args
) {
116 return M
.try_emplace(K
, std::forward
<Ts
>(Args
)...);
118 template <typename
... Ts
>
119 std::pair
<iterator
, bool> try_emplace(ObjectKey
&&K
, Ts
&&... Args
) {
120 return M
.try_emplace(std::move(K
), std::forward
<Ts
>(Args
)...);
123 iterator
find(StringRef K
) { return M
.find_as(K
); }
124 const_iterator
find(StringRef K
) const { return M
.find_as(K
); }
125 // operator[] acts as if Value was default-constructible as null.
126 Value
&operator[](const ObjectKey
&K
);
127 Value
&operator[](ObjectKey
&&K
);
128 // Look up a property, returning nullptr if it doesn't exist.
129 Value
*get(StringRef K
);
130 const Value
*get(StringRef K
) const;
131 // Typed accessors return None/nullptr if
132 // - the property doesn't exist
133 // - or it has the wrong type
134 llvm::Optional
<std::nullptr_t
> getNull(StringRef K
) const;
135 llvm::Optional
<bool> getBoolean(StringRef K
) const;
136 llvm::Optional
<double> getNumber(StringRef K
) const;
137 llvm::Optional
<int64_t> getInteger(StringRef K
) const;
138 llvm::Optional
<llvm::StringRef
> getString(StringRef K
) const;
139 const json::Object
*getObject(StringRef K
) const;
140 json::Object
*getObject(StringRef K
);
141 const json::Array
*getArray(StringRef K
) const;
142 json::Array
*getArray(StringRef K
);
144 bool operator==(const Object
&LHS
, const Object
&RHS
);
145 inline bool operator!=(const Object
&LHS
, const Object
&RHS
) {
146 return !(LHS
== RHS
);
149 /// An Array is a JSON array, which contains heterogeneous JSON values.
150 /// It simulates std::vector<Value>.
152 std::vector
<Value
> V
;
155 using value_type
= Value
;
156 using iterator
= std::vector
<Value
>::iterator
;
157 using const_iterator
= std::vector
<Value
>::const_iterator
;
159 explicit Array() = default;
160 explicit Array(std::initializer_list
<Value
> Elements
);
161 template <typename Collection
> explicit Array(const Collection
&C
) {
162 for (const auto &V
: C
)
166 Value
&operator[](size_t I
) { return V
[I
]; }
167 const Value
&operator[](size_t I
) const { return V
[I
]; }
168 Value
&front() { return V
.front(); }
169 const Value
&front() const { return V
.front(); }
170 Value
&back() { return V
.back(); }
171 const Value
&back() const { return V
.back(); }
172 Value
*data() { return V
.data(); }
173 const Value
*data() const { return V
.data(); }
175 iterator
begin() { return V
.begin(); }
176 const_iterator
begin() const { return V
.begin(); }
177 iterator
end() { return V
.end(); }
178 const_iterator
end() const { return V
.end(); }
180 bool empty() const { return V
.empty(); }
181 size_t size() const { return V
.size(); }
183 void clear() { V
.clear(); }
184 void push_back(const Value
&E
) { V
.push_back(E
); }
185 void push_back(Value
&&E
) { V
.push_back(std::move(E
)); }
186 template <typename
... Args
> void emplace_back(Args
&&... A
) {
187 V
.emplace_back(std::forward
<Args
>(A
)...);
189 void pop_back() { V
.pop_back(); }
190 // FIXME: insert() takes const_iterator since C++11, old libstdc++ disagrees.
191 iterator
insert(iterator P
, const Value
&E
) { return V
.insert(P
, E
); }
192 iterator
insert(iterator P
, Value
&&E
) {
193 return V
.insert(P
, std::move(E
));
195 template <typename It
> iterator
insert(iterator P
, It A
, It Z
) {
196 return V
.insert(P
, A
, Z
);
198 template <typename
... Args
> iterator
emplace(const_iterator P
, Args
&&... A
) {
199 return V
.emplace(P
, std::forward
<Args
>(A
)...);
202 friend bool operator==(const Array
&L
, const Array
&R
) { return L
.V
== R
.V
; }
204 inline bool operator!=(const Array
&L
, const Array
&R
) { return !(L
== R
); }
206 /// A Value is an JSON value of unknown type.
207 /// They can be copied, but should generally be moved.
209 /// === Composing values ===
211 /// You can implicitly construct Values from:
212 /// - strings: std::string, SmallString, formatv, StringRef, char*
213 /// (char*, and StringRef are references, not copies!)
217 /// - arrays: {"foo", 42.0, false}
218 /// - serializable things: types with toJSON(const T&)->Value, found by ADL
220 /// They can also be constructed from object/array helpers:
221 /// - json::Object is a type like map<ObjectKey, Value>
222 /// - json::Array is a type like vector<Value>
223 /// These can be list-initialized, or used to build up collections in a loop.
224 /// json::ary(Collection) converts all items in a collection to Values.
226 /// === Inspecting values ===
228 /// Each Value is one of the JSON kinds:
231 /// number (double or int64)
232 /// string (StringRef)
233 /// array (json::Array)
234 /// object (json::Object)
236 /// The kind can be queried directly, or implicitly via the typed accessors:
237 /// if (Optional<StringRef> S = E.getAsString()
238 /// assert(E.kind() == Value::String);
240 /// Array and Object also have typed indexing accessors for easy traversal:
241 /// Expected<Value> E = parse(R"( {"options": {"font": "sans-serif"}} )");
242 /// if (Object* O = E->getAsObject())
243 /// if (Object* Opts = O->getObject("options"))
244 /// if (Optional<StringRef> Font = Opts->getString("font"))
245 /// assert(Opts->at("font").kind() == Value::String);
247 /// === Converting JSON values to C++ types ===
249 /// The convention is to have a deserializer function findable via ADL:
250 /// fromJSON(const json::Value&, T&)->bool
251 /// Deserializers are provided for:
253 /// - int and int64_t
256 /// - vector<T>, where T is deserializable
257 /// - map<string, T>, where T is deserializable
258 /// - Optional<T>, where T is deserializable
259 /// ObjectMapper can help writing fromJSON() functions for object types.
261 /// For conversion in the other direction, the serializer function is:
262 /// toJSON(const T&) -> json::Value
263 /// If this exists, then it also allows constructing Value from T, and can
264 /// be used to serialize vector<T>, map<string, T>, and Optional<T>.
266 /// === Serialization ===
268 /// Values can be serialized to JSON:
269 /// 1) raw_ostream << Value // Basic formatting.
270 /// 2) raw_ostream << formatv("{0}", Value) // Basic formatting.
271 /// 3) raw_ostream << formatv("{0:2}", Value) // Pretty-print with indent 2.
274 /// Expected<Value> E = json::parse("[1, 2, null]");
275 /// assert(E && E->kind() == Value::Array);
281 /// Number values can store both int64s and doubles at full precision,
282 /// depending on what they were constructed/parsed from.
289 // It would be nice to have Value() be null. But that would make {} null too.
290 Value(const Value
&M
) { copyFrom(M
); }
291 Value(Value
&&M
) { moveFrom(std::move(M
)); }
292 Value(std::initializer_list
<Value
> Elements
);
293 Value(json::Array
&&Elements
) : Type(T_Array
) {
294 create
<json::Array
>(std::move(Elements
));
296 template <typename Elt
>
297 Value(const std::vector
<Elt
> &C
) : Value(json::Array(C
)) {}
298 Value(json::Object
&&Properties
) : Type(T_Object
) {
299 create
<json::Object
>(std::move(Properties
));
301 template <typename Elt
>
302 Value(const std::map
<std::string
, Elt
> &C
) : Value(json::Object(C
)) {}
303 // Strings: types with value semantics. Must be valid UTF-8.
304 Value(std::string V
) : Type(T_String
) {
305 if (LLVM_UNLIKELY(!isUTF8(V
))) {
306 assert(false && "Invalid UTF-8 in value used as JSON");
307 V
= fixUTF8(std::move(V
));
309 create
<std::string
>(std::move(V
));
311 Value(const llvm::SmallVectorImpl
<char> &V
)
312 : Value(std::string(V
.begin(), V
.end())){};
313 Value(const llvm::formatv_object_base
&V
) : Value(V
.str()){};
314 // Strings: types with reference semantics. Must be valid UTF-8.
315 Value(StringRef V
) : Type(T_StringRef
) {
316 create
<llvm::StringRef
>(V
);
317 if (LLVM_UNLIKELY(!isUTF8(V
))) {
318 assert(false && "Invalid UTF-8 in value used as JSON");
319 *this = Value(fixUTF8(V
));
322 Value(const char *V
) : Value(StringRef(V
)) {}
323 Value(std::nullptr_t
) : Type(T_Null
) {}
324 // Boolean (disallow implicit conversions).
325 // (The last template parameter is a dummy to keep templates distinct.)
328 typename
= typename
std::enable_if
<std::is_same
<T
, bool>::value
>::type
,
330 Value(T B
) : Type(T_Boolean
) {
333 // Integers (except boolean). Must be non-narrowing convertible to int64_t.
336 typename
= typename
std::enable_if
<std::is_integral
<T
>::value
>::type
,
337 typename
= typename
std::enable_if
<!std::is_same
<T
, bool>::value
>::type
>
338 Value(T I
) : Type(T_Integer
) {
339 create
<int64_t>(int64_t{I
});
341 // Floating point. Must be non-narrowing convertible to double.
342 template <typename T
,
344 typename
std::enable_if
<std::is_floating_point
<T
>::value
>::type
,
346 Value(T D
) : Type(T_Double
) {
347 create
<double>(double{D
});
349 // Serializable types: with a toJSON(const T&)->Value function, found by ADL.
350 template <typename T
,
351 typename
= typename
std::enable_if
<std::is_same
<
352 Value
, decltype(toJSON(*(const T
*)nullptr))>::value
>,
354 Value(const T
&V
) : Value(toJSON(V
)) {}
356 Value
&operator=(const Value
&M
) {
361 Value
&operator=(Value
&&M
) {
363 moveFrom(std::move(M
));
366 ~Value() { destroy(); }
385 llvm_unreachable("Unknown kind");
388 // Typed accessors return None/nullptr if the Value is not of this type.
389 llvm::Optional
<std::nullptr_t
> getAsNull() const {
390 if (LLVM_LIKELY(Type
== T_Null
))
394 llvm::Optional
<bool> getAsBoolean() const {
395 if (LLVM_LIKELY(Type
== T_Boolean
))
399 llvm::Optional
<double> getAsNumber() const {
400 if (LLVM_LIKELY(Type
== T_Double
))
402 if (LLVM_LIKELY(Type
== T_Integer
))
403 return as
<int64_t>();
406 // Succeeds if the Value is a Number, and exactly representable as int64_t.
407 llvm::Optional
<int64_t> getAsInteger() const {
408 if (LLVM_LIKELY(Type
== T_Integer
))
409 return as
<int64_t>();
410 if (LLVM_LIKELY(Type
== T_Double
)) {
411 double D
= as
<double>();
412 if (LLVM_LIKELY(std::modf(D
, &D
) == 0.0 &&
413 D
>= double(std::numeric_limits
<int64_t>::min()) &&
414 D
<= double(std::numeric_limits
<int64_t>::max())))
419 llvm::Optional
<llvm::StringRef
> getAsString() const {
420 if (Type
== T_String
)
421 return llvm::StringRef(as
<std::string
>());
422 if (LLVM_LIKELY(Type
== T_StringRef
))
423 return as
<llvm::StringRef
>();
426 const json::Object
*getAsObject() const {
427 return LLVM_LIKELY(Type
== T_Object
) ? &as
<json::Object
>() : nullptr;
429 json::Object
*getAsObject() {
430 return LLVM_LIKELY(Type
== T_Object
) ? &as
<json::Object
>() : nullptr;
432 const json::Array
*getAsArray() const {
433 return LLVM_LIKELY(Type
== T_Array
) ? &as
<json::Array
>() : nullptr;
435 json::Array
*getAsArray() {
436 return LLVM_LIKELY(Type
== T_Array
) ? &as
<json::Array
>() : nullptr;
439 /// Serializes this Value to JSON, writing it to the provided stream.
440 /// The formatting is compact (no extra whitespace) and deterministic.
441 /// For pretty-printing, use the formatv() format_provider below.
442 friend llvm::raw_ostream
&operator<<(llvm::raw_ostream
&, const Value
&);
446 void copyFrom(const Value
&M
);
447 // We allow moving from *const* Values, by marking all members as mutable!
448 // This hack is needed to support initializer-list syntax efficiently.
449 // (std::initializer_list<T> is a container of const T).
450 void moveFrom(const Value
&&M
);
454 template <typename T
, typename
... U
> void create(U
&&... V
) {
455 new (reinterpret_cast<T
*>(Union
.buffer
)) T(std::forward
<U
>(V
)...);
457 template <typename T
> T
&as() const {
458 // Using this two-step static_cast via void * instead of reinterpret_cast
459 // silences a -Wstrict-aliasing false positive from GCC6 and earlier.
460 void *Storage
= static_cast<void *>(Union
.buffer
);
461 return *static_cast<T
*>(Storage
);
464 template <typename Indenter
>
465 void print(llvm::raw_ostream
&, const Indenter
&) const;
466 friend struct llvm::format_provider
<llvm::json::Value
>;
468 enum ValueType
: char {
478 // All members mutable, see moveFrom().
479 mutable ValueType Type
;
480 mutable llvm::AlignedCharArrayUnion
<bool, double, int64_t, llvm::StringRef
,
481 std::string
, json::Array
, json::Object
>
483 friend bool operator==(const Value
&, const Value
&);
486 bool operator==(const Value
&, const Value
&);
487 inline bool operator!=(const Value
&L
, const Value
&R
) { return !(L
== R
); }
488 llvm::raw_ostream
&operator<<(llvm::raw_ostream
&, const Value
&);
490 /// ObjectKey is a used to capture keys in Object. Like Value but:
491 /// - only strings are allowed
492 /// - it's optimized for the string literal case (Owned == nullptr)
493 /// Like Value, strings must be UTF-8. See isUTF8 documentation for details.
496 ObjectKey(const char *S
) : ObjectKey(StringRef(S
)) {}
497 ObjectKey(std::string S
) : Owned(new std::string(std::move(S
))) {
498 if (LLVM_UNLIKELY(!isUTF8(*Owned
))) {
499 assert(false && "Invalid UTF-8 in value used as JSON");
500 *Owned
= fixUTF8(std::move(*Owned
));
504 ObjectKey(llvm::StringRef S
) : Data(S
) {
505 if (LLVM_UNLIKELY(!isUTF8(Data
))) {
506 assert(false && "Invalid UTF-8 in value used as JSON");
507 *this = ObjectKey(fixUTF8(S
));
510 ObjectKey(const llvm::SmallVectorImpl
<char> &V
)
511 : ObjectKey(std::string(V
.begin(), V
.end())) {}
512 ObjectKey(const llvm::formatv_object_base
&V
) : ObjectKey(V
.str()) {}
514 ObjectKey(const ObjectKey
&C
) { *this = C
; }
515 ObjectKey(ObjectKey
&&C
) : ObjectKey(static_cast<const ObjectKey
&&>(C
)) {}
516 ObjectKey
&operator=(const ObjectKey
&C
) {
518 Owned
.reset(new std::string(*C
.Owned
));
525 ObjectKey
&operator=(ObjectKey
&&) = default;
527 operator llvm::StringRef() const { return Data
; }
528 std::string
str() const { return Data
.str(); }
531 // FIXME: this is unneccesarily large (3 pointers). Pointer + length + owned
532 // could be 2 pointers at most.
533 std::unique_ptr
<std::string
> Owned
;
534 llvm::StringRef Data
;
537 inline bool operator==(const ObjectKey
&L
, const ObjectKey
&R
) {
538 return llvm::StringRef(L
) == llvm::StringRef(R
);
540 inline bool operator!=(const ObjectKey
&L
, const ObjectKey
&R
) {
543 inline bool operator<(const ObjectKey
&L
, const ObjectKey
&R
) {
544 return StringRef(L
) < StringRef(R
);
552 inline Object::Object(std::initializer_list
<KV
> Properties
) {
553 for (const auto &P
: Properties
) {
554 auto R
= try_emplace(P
.K
, nullptr);
556 R
.first
->getSecond().moveFrom(std::move(P
.V
));
559 inline std::pair
<Object::iterator
, bool> Object::insert(KV E
) {
560 return try_emplace(std::move(E
.K
), std::move(E
.V
));
563 // Standard deserializers are provided for primitive types.
564 // See comments on Value.
565 inline bool fromJSON(const Value
&E
, std::string
&Out
) {
566 if (auto S
= E
.getAsString()) {
572 inline bool fromJSON(const Value
&E
, int &Out
) {
573 if (auto S
= E
.getAsInteger()) {
579 inline bool fromJSON(const Value
&E
, int64_t &Out
) {
580 if (auto S
= E
.getAsInteger()) {
586 inline bool fromJSON(const Value
&E
, double &Out
) {
587 if (auto S
= E
.getAsNumber()) {
593 inline bool fromJSON(const Value
&E
, bool &Out
) {
594 if (auto S
= E
.getAsBoolean()) {
600 template <typename T
> bool fromJSON(const Value
&E
, llvm::Optional
<T
> &Out
) {
606 if (!fromJSON(E
, Result
))
608 Out
= std::move(Result
);
611 template <typename T
> bool fromJSON(const Value
&E
, std::vector
<T
> &Out
) {
612 if (auto *A
= E
.getAsArray()) {
614 Out
.resize(A
->size());
615 for (size_t I
= 0; I
< A
->size(); ++I
)
616 if (!fromJSON((*A
)[I
], Out
[I
]))
622 template <typename T
>
623 bool fromJSON(const Value
&E
, std::map
<std::string
, T
> &Out
) {
624 if (auto *O
= E
.getAsObject()) {
626 for (const auto &KV
: *O
)
627 if (!fromJSON(KV
.second
, Out
[llvm::StringRef(KV
.first
)]))
634 // Allow serialization of Optional<T> for supported T.
635 template <typename T
> Value
toJSON(const llvm::Optional
<T
> &Opt
) {
636 return Opt
? Value(*Opt
) : Value(nullptr);
639 /// Helper for mapping JSON objects onto protocol structs.
643 /// bool fromJSON(const Value &E, MyStruct &R) {
644 /// ObjectMapper O(E);
645 /// if (!O || !O.map("mandatory_field", R.MandatoryField))
647 /// O.map("optional_field", R.OptionalField);
653 ObjectMapper(const Value
&E
) : O(E
.getAsObject()) {}
655 /// True if the expression is an object.
656 /// Must be checked before calling map().
657 operator bool() { return O
; }
659 /// Maps a property to a field, if it exists.
660 template <typename T
> bool map(StringRef Prop
, T
&Out
) {
661 assert(*this && "Must check this is an object before calling map()");
662 if (const Value
*E
= O
->get(Prop
))
663 return fromJSON(*E
, Out
);
667 /// Maps a property to a field, if it exists.
668 /// (Optional requires special handling, because missing keys are OK).
669 template <typename T
> bool map(StringRef Prop
, llvm::Optional
<T
> &Out
) {
670 assert(*this && "Must check this is an object before calling map()");
671 if (const Value
*E
= O
->get(Prop
))
672 return fromJSON(*E
, Out
);
681 /// Parses the provided JSON source, or returns a ParseError.
682 /// The returned Value is self-contained and owns its strings (they do not refer
683 /// to the original source).
684 llvm::Expected
<Value
> parse(llvm::StringRef JSON
);
686 class ParseError
: public llvm::ErrorInfo
<ParseError
> {
688 unsigned Line
, Column
, Offset
;
692 ParseError(const char *Msg
, unsigned Line
, unsigned Column
, unsigned Offset
)
693 : Msg(Msg
), Line(Line
), Column(Column
), Offset(Offset
) {}
694 void log(llvm::raw_ostream
&OS
) const override
{
695 OS
<< llvm::formatv("[{0}:{1}, byte={2}]: {3}", Line
, Column
, Offset
, Msg
);
697 std::error_code
convertToErrorCode() const override
{
698 return llvm::inconvertibleErrorCode();
703 /// Allow printing json::Value with formatv().
704 /// The default style is basic/compact formatting, like operator<<.
705 /// A format string like formatv("{0:2}", Value) pretty-prints with indent 2.
706 template <> struct format_provider
<llvm::json::Value
> {
707 static void format(const llvm::json::Value
&, raw_ostream
&, StringRef
);