簡體   English   中英

如何使用 System.Text.Json 將 json 數組轉換為集合;

[英]How to convert json array to collection with System.Text.Json;

我有一個User class 具有ISet<Role>類型的屬性Roles ,其中Roleenum類型。 在 JSON 中,我得到了該屬性的數組(例如, "Roles":["Admin","User"] )。 如何編寫自定義轉換器將此數組轉換為ISet集合?

我試過寫這個 class:

class CustomStringToRoleConverter : JsonConverter<ISet<User.Role>> {
    public override ISet<User.Role> Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) {
        return null;
    }

    public override void Write(Utf8JsonWriter writer, ISet<User.Role> roles, JsonSerializerOptions options) {
        StringBuilder builder = new StringBuilder();
        builder.Append(string.Join(",", roles.Select(role => role.ToString()).ToArray()));
        writer.WriteStartArray();
        writer.WriteStringValue(builder.ToString());
        writer.WriteEndArray();
    }
}

但我不知道在Read方法中該怎么做。 如何從Utf8JsonReader獲取數組? 有一個GetString方法,但是當我調用它時它會引發異常:

InvalidOperationException:無法將令牌類型“StartArray”的值作為字符串獲取。

我正在使用System.TextSystem.Text.Json

JSON "Roles":["Admin","User"]屬性是一個字符串值數組,而不是包含逗號分隔值的單個字符串值。 因此,編寫自定義轉換器的最簡單方法如下:

class CustomStringToRoleConverter : JsonConverter<ISet<User.Role>> {
    public override ISet<User.Role> Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) =>
        JsonSerializer.Deserialize<List<string>>(ref reader, options)
            ?.Select(s => Enum.Parse<User.Role>(s))
            ?.ToHashSet(); // Or use a SortedSet if you prefer

    public override void Write(Utf8JsonWriter writer, ISet<User.Role> roles, JsonSerializerOptions options) =>
        JsonSerializer.Serialize(writer, roles.Select(r => r.ToString()), options);
}

轉換器只是對字符串集合進行序列化和反序列化,然后將項目解析或格式化為Role枚舉,作為后處理或預處理步驟。 (為了比較,您現有的Write()方法將生成"Roles": ["Admin,User"]與問題開頭段落中顯示的 JSON 不匹配。)

樣品小提琴#1在這里

如果您非常關心性能並且更喜歡不反序列化為中間List<string>的更“手動”方法,您可以這樣做:

class CustomStringToRoleConverter : JsonConverter<ISet<User.Role>> {
    public override ISet<User.Role> Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        if (reader.TokenType == JsonTokenType.Null)
            return null; // Or throw an exception if you don't want to allow null
        else if (reader.TokenType != JsonTokenType.StartArray)
            throw new JsonException();
        var set = new HashSet<User.Role>();
        while (reader.Read())
        {
            if (reader.TokenType == JsonTokenType.EndArray)
                return set;
            else if (reader.TokenType == JsonTokenType.String)
                set.Add(Enum.Parse<User.Role>(reader.GetString()));
            else
            {
                //reader.Skip();
                throw new JsonException(); // Unexpected token;
            }
        }
        throw new JsonException(); // Truncated file;
    }

    public override void Write(Utf8JsonWriter writer, ISet<User.Role> roles, JsonSerializerOptions options)
    {
        writer.WriteStartArray();
        foreach (var value in roles)
            writer.WriteStringValue(value.ToString());
        writer.WriteEndArray();
    }
}

樣品小提琴#2在這里

或者,您可以簡單地將JsonStringEnumConverter添加到JsonSerializerOptions.Converters以將所有枚舉序列化為字符串。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM