using Newtonsoft.Json; using Newtonsoft.Json.Linq; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace KssSmaPlaLib.IO.File { public static class JsonFileUxer { /// /// JSONファイルのピンポイント1項目更新 /// /// JSONファイルパス /// JSONノードパス /// 更新値 /// // public static void UpdateJsonKeyAtomic(string path, string jsonPath, object newValue) // { // //// 使い方例:パスワード更新 // //JsonFiileUxer.UpdateJsonKeyAtomic("config.json", "app.auth.password", "new_pw_2026-01"); // var jtoken = JToken.FromObject(newValue); // // 1) 読み込み(UTF-8) // var json = System.IO.File.ReadAllText(path, new UTF8Encoding(encoderShouldEmitUTF8Identifier: false)); // var jo = JObject.Parse(json); // // 2) ピンポイント更新(途中が無ければ作る) // var token = jo.SelectToken(jsonPath); // if (token is null) // { // // 例: "app.auth.password" を分解して動的に作る // var parts = jsonPath.Split('.'); // JToken cur = jo; // for (int i = 0; i < parts.Length; i++) // { // var name = parts[i]; // var obj = cur as JObject ?? throw new InvalidOperationException("親がオブジェクトではありません"); // if (i == parts.Length - 1) // { // obj[name] = jtoken; // } // else // { // if (obj[name] == null) obj[name] = new JObject(); // cur = obj[name]; // } // } // } // else // { // token.Replace(jtoken); // } // // 3) 一時ファイルへ書き出し // var dir = System.IO.Path.GetDirectoryName(path) ?? "."; // var tmp = System.IO.Path.Combine(dir, ".tmp_config.json"); // var backup = path + $"_{DateTime.Now.ToString("yyyyMMddHHmmss")}" + ".bak"; // //var output = jo.ToString(Formatting.Indented) + Environment.NewLine; // var output = JsonConvert.SerializeObject(jo, Formatting.Indented) + Environment.NewLine; // System.IO.File.WriteAllText(tmp, output, new UTF8Encoding(false)); // // 4) バックアップ作成 → 原子置換 // if (System.IO.File.Exists(path)) System.IO.File.Copy(path, backup, overwrite: true); // System.IO.File.Replace(tmp, path, backup); // } /// /// JSONファイルから、jsonPathに一致する単一項目を取得します。 /// 取得に成功したら true を返し、 out value に JToken を設定します。 /// キーが見つからない・JSON無効・ファイル無し等は false を返し、 value は null。 /// // public static bool TryGetJsonKey(string path, string jsonPath, out JToken value) // { // value = null; // // 1) 読み込み(UTF-8 BOMなし) // string json; // try // { // json = System.IO.File.ReadAllText(path, new UTF8Encoding(encoderShouldEmitUTF8Identifier: false)); // } // catch (Exception) // { // // ファイルがない/読み取り不可 // return false; // } // // 2) 解析 // JObject jo; // try // { // jo = JObject.Parse(json); // } // catch (JsonReaderException) // { // // JSON不正 // return false; // } // // 3) ピンポイント取得 // // 例: "app.auth.password" / "items[0].name" / "users['alice'].age" 等 // try // { // var token = jo.SelectToken(jsonPath); // if (token is null) // { // return false; // キー未存在 // } // value = token; // JValue/JObject/JArray いずれもOK // return true; // } // catch (ArgumentException) // { // // JSONPathの書式誤り(SelectTokenが例外) // return false; // } // } /// /// 文字列として取得(JToken型を意識したくない場合の軽量ヘルパー)。 /// // public static bool TryGetJsonString(string path, string jsonPath, out string result) // { // result = string.Empty; // if (!TryGetJsonKey(path, jsonPath, out var token)) return false; // // JValue以外(オブジェクト/配列)の場合は ToString() を許容するか判断(ここではJValueのみ厳密) // if (token is JValue jv) // { // // 文字列ならそのまま // if (jv.Type == JTokenType.String) // { // result = (string)jv.Value; // return true; // } // // 数値・真偽・Null などは ToString() で返す設計でもOK // // ここでは文字列のみ厳密に true とします(お好みで分岐調整) // return false; // } // return false; // } /// /// 符号付き整数(Int64)で取得(intの範囲超えも想定)。 /// // public static bool TryGetJsonInt64(string path, string jsonPath, out long result) // { // result = default; // if (!TryGetJsonKey(path, jsonPath, out var token)) return false; // if (token is JValue jv) // { // // JValueが数値型なら long へ // if (jv.Type == JTokenType.Integer) // { // // Newtonsoftは内部的に long を持つのでキャスト可能 // try // { // result = Convert.ToInt64(jv.Value); // return true; // } // catch // { // return false; // } // } // // 文字列数値を許可する場合("42" → 42) // if (jv.Type == JTokenType.String && long.TryParse((string)jv.Value, out var parsed)) // { // result = parsed; // return true; // } // } // return false; // } /// /// 任意型の既定値付き取得(存在しなければ defaultValue を返す)。 /// 例:GetJsonKeyOrDefault(path, "app.auth.retries", 3) /// // public static T GetJsonKeyOrDefault(string path, string jsonPath, T defaultValue) // { // if (!TryGetJsonKey(path, jsonPath, out var token) || token is null) // return defaultValue; // try // { // // JToken → 任意型に変換(失敗時は既定値) // var val = token.ToObject(); // return val == null ? defaultValue : val; // } // catch // { // return defaultValue; // } // } } }