Skip to content

Commit 4087cff

Browse files
committed
[JSONSerialization] Add ability to emit 'null' value
1 parent 993f623 commit 4087cff

File tree

2 files changed

+57
-0
lines changed

2 files changed

+57
-0
lines changed

include/swift/Basic/JSONSerialization.h

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,30 @@ struct ScalarTraits {
110110
};
111111

112112

113+
/// This class should be specialized by any type that can be 'null' in JSON.
114+
/// For example:
115+
///
116+
/// template<>
117+
/// struct NullableTraits<MyType *> > {
118+
/// static bool isNull(MyType *&ptr) {
119+
/// return !ptr;
120+
/// }
121+
/// static MyType &get(MyType *&ptr) {
122+
/// return *ptr;
123+
/// }
124+
/// };
125+
template<typename T>
126+
struct NullableTraits {
127+
// Must provide:
128+
//
129+
// Function to return true if the value is 'null'.
130+
// static bool isNull(const T &Val);
131+
//
132+
// Function to return a reference to the unwrapped value.
133+
// static T::value_type &get(const T &Val);
134+
};
135+
136+
113137
/// This class should be specialized by any type that needs to be converted
114138
/// to/from a JSON array. For example:
115139
///
@@ -249,6 +273,23 @@ template<typename T>
249273
struct has_ArrayTraits : public std::integral_constant<bool,
250274
has_ArrayMethodTraits<T>::value > { };
251275

276+
// Test if NullableTraits<T> is defined on type T.
277+
template <class T>
278+
struct has_NullableTraits
279+
{
280+
typedef bool (*Signature_isNull)(T&);
281+
282+
template <typename U>
283+
static char test(SameType<Signature_isNull, &U::isNull> *);
284+
285+
template <typename U>
286+
static double test(...);
287+
288+
public:
289+
static bool const value =
290+
(sizeof(test<NullableTraits<T>>(nullptr)) == 1);
291+
};
292+
252293
inline bool isNumber(StringRef S) {
253294
static const char DecChars[] = "0123456789";
254295
if (S.find_first_not_of(DecChars) == StringRef::npos)
@@ -285,6 +326,7 @@ struct missingTraits : public std::integral_constant<bool,
285326
!has_ScalarEnumerationTraits<T>::value
286327
&& !has_ScalarBitSetTraits<T>::value
287328
&& !has_ScalarTraits<T>::value
329+
&& !has_NullableTraits<T>::value
288330
&& !has_ObjectTraits<T>::value
289331
&& !has_ArrayTraits<T>::value> {};
290332

@@ -338,6 +380,7 @@ class Output {
338380
void endBitSetScalar();
339381

340382
void scalarString(StringRef &, bool);
383+
void null();
341384

342385
template <typename T>
343386
void enumCase(T &Val, const char* Str, const T ConstVal) {
@@ -579,6 +622,16 @@ jsonize(Output &out, T &Val, bool) {
579622
}
580623

581624

625+
template<typename T>
626+
typename std::enable_if<has_NullableTraits<T>::value,void>::type
627+
jsonize(Output &out, T &Obj, bool) {
628+
if (NullableTraits<T>::isNull(Obj))
629+
out.null();
630+
else
631+
jsonize(out, NullableTraits<T>::get(Obj), true);
632+
}
633+
634+
582635
template<typename T>
583636
typename std::enable_if<validatedObjectTraits<T>::value, void>::type
584637
jsonize(Output &out, T &Val, bool) {

lib/Basic/JSONSerialization.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,10 @@ void Output::scalarString(StringRef &S, bool MustQuote) {
222222
Stream << S;
223223
}
224224

225+
void Output::null() {
226+
Stream << "null";
227+
}
228+
225229
void Output::indent() {
226230
Stream.indent(StateStack.size() * 2);
227231
}

0 commit comments

Comments
 (0)