| ... | @@ -197,6 +197,34 @@ pub fn WriteStream(comptime OutStream: type, comptime max_depth: usize) type { | ... | @@ -197,6 +197,34 @@ pub fn WriteStream(comptime OutStream: type, comptime max_depth: usize) type { |
| 197 | try self.stream.writeByte('"'); | 197 | try self.stream.writeByte('"'); |
| 198 | } | 198 | } |
| 199 | | 199 | |
| | 200 | /// Writes the complete json into the output stream |
| | 201 | pub fn emitJson(self: *Self, json: std.json.Value) Stream.Error!void { |
| | 202 | switch (json) { |
| | 203 | .Null => try self.emitNull(), |
| | 204 | .Bool => |inner| try self.emitBool(inner), |
| | 205 | .Integer => |inner| try self.emitNumber(inner), |
| | 206 | .Float => |inner| try self.emitNumber(inner), |
| | 207 | .String => |inner| try self.emitString(inner), |
| | 208 | .Array => |inner| { |
| | 209 | try self.beginArray(); |
| | 210 | for (inner.toSliceConst()) |elem| { |
| | 211 | try self.arrayElem(); |
| | 212 | try self.emitJson(elem); |
| | 213 | } |
| | 214 | try self.endArray(); |
| | 215 | }, |
| | 216 | .Object => |inner| { |
| | 217 | try self.beginObject(); |
| | 218 | var it = inner.iterator(); |
| | 219 | while (it.next()) |entry| { |
| | 220 | try self.objectField(entry.key); |
| | 221 | try self.emitJson(entry.value); |
| | 222 | } |
| | 223 | try self.endObject(); |
| | 224 | }, |
| | 225 | } |
| | 226 | } |
| | 227 | |
| 200 | fn indent(self: *Self) !void { | 228 | fn indent(self: *Self) !void { |
| 201 | assert(self.state_index >= 1); | 229 | assert(self.state_index >= 1); |
| 202 | try self.stream.write(self.newline); | 230 | try self.stream.write(self.newline); |
| ... | @@ -216,3 +244,61 @@ pub fn WriteStream(comptime OutStream: type, comptime max_depth: usize) type { | ... | @@ -216,3 +244,61 @@ pub fn WriteStream(comptime OutStream: type, comptime max_depth: usize) type { |
| 216 | } | 244 | } |
| 217 | }; | 245 | }; |
| 218 | } | 246 | } |
| | 247 | |
| | 248 | test "json write stream" { |
| | 249 | var out_buf: [1024]u8 = undefined; |
| | 250 | var slice_stream = std.io.SliceOutStream.init(&out_buf); |
| | 251 | const out = &slice_stream.stream; |
| | 252 | |
| | 253 | var mem_buf: [1024 * 10]u8 = undefined; |
| | 254 | const allocator = &std.heap.FixedBufferAllocator.init(&mem_buf).allocator; |
| | 255 | |
| | 256 | var w = std.json.WriteStream(@typeOf(out).Child, 10).init(out); |
| | 257 | try w.emitJson(try getJson(allocator)); |
| | 258 | |
| | 259 | const result = slice_stream.getWritten(); |
| | 260 | const expected = |
| | 261 | \\{ |
| | 262 | \\ "object": { |
| | 263 | \\ "one": 1, |
| | 264 | \\ "two": 2.0e+00 |
| | 265 | \\ }, |
| | 266 | \\ "string": "This is a string", |
| | 267 | \\ "array": [ |
| | 268 | \\ "Another string", |
| | 269 | \\ 1, |
| | 270 | \\ 3.14e+00 |
| | 271 | \\ ], |
| | 272 | \\ "int": 10, |
| | 273 | \\ "float": 3.14e+00 |
| | 274 | \\} |
| | 275 | ; |
| | 276 | std.testing.expect(std.mem.eql(u8, expected, result)); |
| | 277 | } |
| | 278 | |
| | 279 | fn getJson(allocator: *std.mem.Allocator) !std.json.Value { |
| | 280 | var value = std.json.Value{ .Object = std.json.ObjectMap.init(allocator) }; |
| | 281 | _ = try value.Object.put("string", std.json.Value{ .String = "This is a string" }); |
| | 282 | _ = try value.Object.put("int", std.json.Value{ .Integer = @intCast(i64, 10) }); |
| | 283 | _ = try value.Object.put("float", std.json.Value{ .Float = 3.14 }); |
| | 284 | _ = try value.Object.put("array", try getJsonArray(allocator)); |
| | 285 | _ = try value.Object.put("object", try getJsonObject(allocator)); |
| | 286 | return value; |
| | 287 | } |
| | 288 | |
| | 289 | fn getJsonObject(allocator: *std.mem.Allocator) !std.json.Value { |
| | 290 | var value = std.json.Value{ .Object = std.json.ObjectMap.init(allocator) }; |
| | 291 | _ = try value.Object.put("one", std.json.Value{ .Integer = @intCast(i64, 1) }); |
| | 292 | _ = try value.Object.put("two", std.json.Value{ .Float = 2.0 }); |
| | 293 | return value; |
| | 294 | } |
| | 295 | |
| | 296 | fn getJsonArray(allocator: *std.mem.Allocator) !std.json.Value { |
| | 297 | var value = std.json.Value{ .Array = std.json.Array.init(allocator) }; |
| | 298 | var array = &value.Array; |
| | 299 | _ = try array.append(std.json.Value{ .String = "Another string" }); |
| | 300 | _ = try array.append(std.json.Value{ .Integer = @intCast(i64, 1) }); |
| | 301 | _ = try array.append(std.json.Value{ .Float = 3.14 }); |
| | 302 | |
| | 303 | return value; |
| | 304 | } |