C# net8 讀取Json字串 並實現 針對json字串內元素名稱搜尋 並返回搜尋的對應元素值 範例

C# net8 讀取Json字串 並實現 針對json字串內元素名稱搜尋 並返回搜尋的對應元素值 範例

C# net8 讀取Json字串 並實現 針對json字串內元素名稱搜尋/尋找(Search) 並返回搜尋的對應元素值 範例


資料來源: chatgpt


C#線上編譯: https://dotnetfiddle.net/


範例功能:

    01.可以全域搜尋 : “”
    02.可以指定根節點 : “OOXX”
    03.可以匹配多次(全部找出來)
    03.可以模糊/精確搜尋 : 包含字串

Code

using System;
using System.Collections.Generic;
using System.Text.Json;

class Program
{
    static void Main()
    {
        string json = @"{
            ""name"": ""John"",
            ""age"": 30,
            ""email"": ""john@example.com"",
            ""address"": {
                ""city"": ""New York"",
                ""zip"": ""10001""
            },
            ""previousCities"": [
                { ""city"": ""Los Angeles"" },
                { ""city"": ""Chicago"" }
            ]
        }";

        string searchKey = "city";
        string startPath = "";//address//previousCities//previousCities[0]  // 指定從哪個節點開始搜尋
        bool partialMatch = false;

        using JsonDocument doc = JsonDocument.Parse(json);
        JsonElement root = doc.RootElement;

        if (TryGetElementAtPath(root, startPath, out JsonElement startElement))
        {
            var results = new Dictionary<string, string>();
            FindInElement(startElement, searchKey, results, partialMatch, "$" + (startPath != "" ? "." + startPath : ""));

            if (results.Count > 0)
            {
                Console.WriteLine($"🔍 在 '{startPath}' 節點下找到與 '{searchKey}' {(partialMatch ? "(模糊)" : "(精確)")} 相符的鍵:");
                foreach (var match in results)
                {
                    Console.WriteLine($"  {match.Key} => {match.Value}");
                }
            }
            else
            {
                Console.WriteLine($"❌ 在 '{startPath}' 中找不到 '{searchKey}'");
            }
        }
        else
        {
            Console.WriteLine($"❌ 找不到指定路徑:{startPath}");
        }
    }

    // 主搜尋邏輯
    static void FindInElement(JsonElement element, string searchKey, Dictionary<string, string> results, bool partialMatch, string currentPath)
    {
        switch (element.ValueKind)
        {
            case JsonValueKind.Object:
                foreach (JsonProperty prop in element.EnumerateObject())
                {
                    string newPath = $"{currentPath}.{prop.Name}";
                    bool isMatch = partialMatch
                        ? prop.Name.Contains(searchKey, StringComparison.OrdinalIgnoreCase)
                        : prop.NameEquals(searchKey);

                    if (isMatch && !results.ContainsKey(newPath))
                        results.Add(newPath, prop.Value.ToString());

                    FindInElement(prop.Value, searchKey, results, partialMatch, newPath);
                }
                break;

            case JsonValueKind.Array:
                int index = 0;
                foreach (JsonElement item in element.EnumerateArray())
                {
                    string newPath = $"{currentPath}[{index}]";
                    FindInElement(item, searchKey, results, partialMatch, newPath);
                    index++;
                }
                break;
        }
    }

    // 根據 JSON 路徑取出對應 JsonElement
    static bool TryGetElementAtPath(JsonElement root, string path, out JsonElement result)
    {
        result = root;

        if (string.IsNullOrEmpty(path))
            return true;

        string[] parts = path.Split('.', StringSplitOptions.RemoveEmptyEntries);

        foreach (string part in parts)
        {
            if (result.ValueKind == JsonValueKind.Object)
            {
                string key = part;
                int bracketIndex = part.IndexOf('[');
                if (bracketIndex != -1)
                {
                    key = part[..bracketIndex];
                }

                if (!result.TryGetProperty(key, out result))
                    return false;

                if (bracketIndex != -1)
                {
                    if (!TryParseArrayAccess(ref result, part[bracketIndex..]))
                        return false;
                }
            }
            else if (result.ValueKind == JsonValueKind.Array)
            {
                if (!TryParseArrayAccess(ref result, part))
                    return false;
            }
            else
            {
                return false;
            }
        }

        return true;
    }

    static bool TryParseArrayAccess(ref JsonElement element, string bracketPart)
    {
        while (bracketPart.StartsWith("["))
        {
            int endBracket = bracketPart.IndexOf(']');
            if (endBracket == -1)
                return false;

            string indexStr = bracketPart[1..endBracket];
            if (!int.TryParse(indexStr, out int index))
                return false;

            if (element.ValueKind != JsonValueKind.Array || element.GetArrayLength() <= index)
                return false;

            element = element[index];

            bracketPart = bracketPart[(endBracket + 1)..];
        }

        return true;
    }
}
/*
🔍 在 '' 節點下找到與 'city' (精確) 相符的鍵:
  $.address.city => New York
  $.previousCities[0].city => Los Angeles
  $.previousCities[1].city => Chicago
*/

發表迴響

你的電子郵件位址並不會被公開。 必要欄位標記為 *