using System.Collections;
using System.Collections.Generic;
using System.Runtime.Serialization.Formatters;
using System.ComponentModel.DataAnnotations;
using System.Globalization;
using System.Collections.ObjectModel;
using System.Threading.Tasks;
using System.Text.Json.Nodes;
using System.Text.Json.Serialization;
public static partial class JsonExtensions
public static TNode? CopyNode<TNode>(this TNode? node) where TNode : JsonNode => node?.Deserialize<TNode>();
public static JsonNode? MoveNode(this JsonArray array, int id, JsonObject newParent, string name)
return newParent[name] = node;
public static JsonNode? MoveNode(this JsonObject parent, string oldName, JsonObject newParent, string name)
parent.Remove(oldName, out var node);
return newParent[name] = node;
public static TNode ThrowOnNull<TNode>(this TNode? value) where TNode : JsonNode => value ?? throw new JsonException("Null JSON value");
public static partial class JsonExtensions
public static string concQuest(string input, string allQuest, string questId)
var inputObject = JsonNode.Parse(input).ThrowOnNull().AsObject();
var allQuestArray = JsonNode.Parse(allQuest).ThrowOnNull().AsArray();
concQuest(inputObject, allQuestArray, questId);
return inputObject.ToJsonString();
public static JsonNode? concQuest(JsonObject inputObject, JsonArray allQuestArray, string questId)
var node = allQuestArray.First(quest => quest!["id"]!.GetValue<string>() == questId);
return inputObject["quest"] = node.CopyNode();
public static async Task Test()
var allQuestString = @"[{""id"":""1"", ""name"":""quest 1""},{""id"":""2"", ""name"":""quest 2""}]";
var inputString = @"{""header"":""header value"", ""nullValue"":null}";
var allQuestFileName = @"Question71570877-allquests.json";
var inputFileName = @"Question71570877-quest.json";
Console.WriteLine(inputString);
await File.WriteAllTextAsync(allQuestFileName, allQuestString);
await File.WriteAllTextAsync(inputFileName, inputString);
using (var stream = new FileStream(allQuestFileName, new FileStreamOptions { Mode = FileMode.Open, Access = FileAccess.Read }))
allQuest = JsonNode.Parse(stream).ThrowOnNull().AsArray();
using (var stream = new FileStream(inputFileName, new FileStreamOptions { Mode = FileMode.Open, Access = FileAccess.Read }))
input = JsonNode.Parse(stream).ThrowOnNull().AsObject();
JsonExtensions.concQuest(input, allQuest, questId);
using (var stream = new FileStream(inputFileName, new FileStreamOptions { Mode = FileMode.Create, Access = FileAccess.Write }))
using (var writer = new Utf8JsonWriter(stream, new JsonWriterOptions { Indented = true }))
Console.WriteLine(await File.ReadAllTextAsync(inputFileName));
static void TestObjectObjectMove()
var json = @"{""a"": {""b"": ""value""}}";
var parent = JsonNode.Parse(json).ThrowOnNull().AsObject();
var newParent = new JsonObject();
Assert.Throws<InvalidOperationException>(() => newParent["newA"] = parent["a"]);
var newNode = parent.MoveNode("a", newParent, "newA");
Assert.AreEqual(@"{""newA"":{""b"":""value""}}", JsonSerializer.Serialize(newParent));
public static async Task Main(string[] args)
Console.WriteLine("Environment version: {0} ({1})", Environment.Version, System.Runtime.InteropServices.RuntimeInformation.FrameworkDescription);
Console.WriteLine("{0} version: {1}", typeof(JsonSerializer).Assembly.GetName().Name, typeof(JsonSerializer).Assembly.FullName);
Console.WriteLine("Failed with unhandled exception: ");