| ... | ... | @@ -1233,6 +1233,57 @@ pub const Value = union(enum) { |
| 1233 | 1233 | Array: Array, |
| 1234 | 1234 | Object: ObjectMap, |
| 1235 | 1235 | |
| 1236 | pub fn jsonStringify( |
| 1237 | value: @This(), |
| 1238 | options: StringifyOptions, |
| 1239 | out_stream: var, |
| 1240 | ) @TypeOf(out_stream).Error!void { |
| 1241 | switch (value) { |
| 1242 | .Null => try out_stream.writeAll("null"), |
| 1243 | .Bool => |inner| try stringify(inner, options, out_stream), |
| 1244 | .Integer => |inner| try stringify(inner, options, out_stream), |
| 1245 | .Float => |inner| try stringify(inner, options, out_stream), |
| 1246 | .String => |inner| try stringify(inner, options, out_stream), |
| 1247 | .Array => |inner| try stringify(inner.span(), options, out_stream), |
| 1248 | .Object => |inner| { |
| 1249 | try out_stream.writeByte('{'); |
| 1250 | var field_output = false; |
| 1251 | var child_options = options; |
| 1252 | if (child_options.whitespace) |*child_whitespace| { |
| 1253 | child_whitespace.indent_level += 1; |
| 1254 | } |
| 1255 | var it = inner.iterator(); |
| 1256 | while (it.next()) |entry| { |
| 1257 | if (!field_output) { |
| 1258 | field_output = true; |
| 1259 | } else { |
| 1260 | try out_stream.writeByte(','); |
| 1261 | } |
| 1262 | if (child_options.whitespace) |child_whitespace| { |
| 1263 | try out_stream.writeByte('\n'); |
| 1264 | try child_whitespace.outputIndent(out_stream); |
| 1265 | } |
| 1266 | |
| 1267 | try stringify(entry.key, options, out_stream); |
| 1268 | try out_stream.writeByte(':'); |
| 1269 | if (child_options.whitespace) |child_whitespace| { |
| 1270 | if (child_whitespace.separator) { |
| 1271 | try out_stream.writeByte(' '); |
| 1272 | } |
| 1273 | } |
| 1274 | try stringify(entry.value, child_options, out_stream); |
| 1275 | } |
| 1276 | if (field_output) { |
| 1277 | if (options.whitespace) |whitespace| { |
| 1278 | try out_stream.writeByte('\n'); |
| 1279 | try whitespace.outputIndent(out_stream); |
| 1280 | } |
| 1281 | } |
| 1282 | try out_stream.writeByte('}'); |
| 1283 | }, |
| 1284 | } |
| 1285 | } |
| 1286 | |
| 1236 | 1287 | pub fn dump(self: Value) void { |
| 1237 | 1288 | var held = std.debug.getStderrMutex().acquire(); |
| 1238 | 1289 | defer held.release(); |
| ... | ... | @@ -1270,6 +1321,60 @@ pub const Value = union(enum) { |
| 1270 | 1321 | } |
| 1271 | 1322 | }; |
| 1272 | 1323 | |
| 1324 | test "Value.jsonStringify" { |
| 1325 | { |
| 1326 | var buffer: [10]u8 = undefined; |
| 1327 | var fbs = std.io.fixedBufferStream(&buffer); |
| 1328 | try @as(Value, .Null).jsonStringify(.{}, fbs.outStream()); |
| 1329 | testing.expectEqualSlices(u8, fbs.getWritten(), "null"); |
| 1330 | } |
| 1331 | { |
| 1332 | var buffer: [10]u8 = undefined; |
| 1333 | var fbs = std.io.fixedBufferStream(&buffer); |
| 1334 | try (Value{ .Bool = true }).jsonStringify(.{}, fbs.outStream()); |
| 1335 | testing.expectEqualSlices(u8, fbs.getWritten(), "true"); |
| 1336 | } |
| 1337 | { |
| 1338 | var buffer: [10]u8 = undefined; |
| 1339 | var fbs = std.io.fixedBufferStream(&buffer); |
| 1340 | try (Value{ .Integer = 42 }).jsonStringify(.{}, fbs.outStream()); |
| 1341 | testing.expectEqualSlices(u8, fbs.getWritten(), "42"); |
| 1342 | } |
| 1343 | { |
| 1344 | var buffer: [10]u8 = undefined; |
| 1345 | var fbs = std.io.fixedBufferStream(&buffer); |
| 1346 | try (Value{ .Float = 42 }).jsonStringify(.{}, fbs.outStream()); |
| 1347 | testing.expectEqualSlices(u8, fbs.getWritten(), "4.2e+01"); |
| 1348 | } |
| 1349 | { |
| 1350 | var buffer: [10]u8 = undefined; |
| 1351 | var fbs = std.io.fixedBufferStream(&buffer); |
| 1352 | try (Value{ .String = "weeee" }).jsonStringify(.{}, fbs.outStream()); |
| 1353 | testing.expectEqualSlices(u8, fbs.getWritten(), "\"weeee\""); |
| 1354 | } |
| 1355 | { |
| 1356 | var buffer: [10]u8 = undefined; |
| 1357 | var fbs = std.io.fixedBufferStream(&buffer); |
| 1358 | try (Value{ |
| 1359 | .Array = Array.fromOwnedSlice(undefined, &[_]Value{ |
| 1360 | .{ .Integer = 1 }, |
| 1361 | .{ .Integer = 2 }, |
| 1362 | .{ .Integer = 3 }, |
| 1363 | }), |
| 1364 | }).jsonStringify(.{}, fbs.outStream()); |
| 1365 | testing.expectEqualSlices(u8, fbs.getWritten(), "[1,2,3]"); |
| 1366 | } |
| 1367 | { |
| 1368 | var buffer: [10]u8 = undefined; |
| 1369 | var fbs = std.io.fixedBufferStream(&buffer); |
| 1370 | var obj = ObjectMap.init(testing.allocator); |
| 1371 | defer obj.deinit(); |
| 1372 | try obj.putNoClobber("a", .{ .String = "b" }); |
| 1373 | try (Value{ .Object = obj }).jsonStringify(.{}, fbs.outStream()); |
| 1374 | testing.expectEqualSlices(u8, fbs.getWritten(), "{\"a\":\"b\"}"); |
| 1375 | } |
| 1376 | } |
| 1377 | |
| 1273 | 1378 | pub const ParseOptions = struct { |
| 1274 | 1379 | allocator: ?*Allocator = null, |
| 1275 | 1380 | |