如何使用 System.Text.Json 将 double[] 二维数组序列化为 JSON?

2024-01-03

我需要写一个double[,]使用 System.Text.Json 转换为 JSON 文件,但此序列化程序不支持二维数组。我需要一些帮助来转换我的double[,] to a List<List<double>>这样我就可以保存它。

也欢迎使用 System.Text.Json 保存二维数组的其他方法。


由于您正在使用以下命令将 2d 数组序列化为 JSONSystem.Text.Json,您可以结合以下答案在 C# 中将多维数组转换为锯齿状数组 https://stackoverflow.com/q/21986909/3744182 and 将锯齿状数组转换为二维数组 C# https://stackoverflow.com/q/26291609/3744182创建一个JsonConverterFactory https://learn.microsoft.com/en-us/dotnet/standard/serialization/system-text-json-converters-how-to?pivots=dotnet-5-0#sample-factory-pattern-converter将任何二维数组序列化为 JSON,如下所示:

public class Array2DConverter : JsonConverterFactory
{
    public override bool CanConvert(Type typeToConvert) => typeToConvert.IsArray && typeToConvert.GetArrayRank() == 2;

    public override JsonConverter CreateConverter(Type type, JsonSerializerOptions options) =>
        (JsonConverter)Activator.CreateInstance(
            typeof(Array2DConverterInner<>).MakeGenericType(new [] { type.GetElementType() }),
            BindingFlags.Instance | BindingFlags.Public,
            binder: null,
            args: new object[] { options },
            culture: null);         
    
    class Array2DConverterInner<T> : JsonConverter<T [,]>
    {
        readonly JsonConverter<T> _valueConverter;

        public Array2DConverterInner(JsonSerializerOptions options) =>
            this._valueConverter = (typeof(T) == typeof(object) ? null : (JsonConverter<T>)options.GetConverter(typeof(T))); // Encountered a bug using the builtin ObjectConverter 
        
        public override void Write(Utf8JsonWriter writer, T [,] array, JsonSerializerOptions options)
        {
            // Adapted from this answer https://stackoverflow.com/a/25995025/3744182
            // By https://stackoverflow.com/users/3258160/pedro
            // To https://stackoverflow.com/questions/21986909/convert-multidimensional-array-to-jagged-array-in-c-sharp
            var rowsFirstIndex = array.GetLowerBound(0);
            var rowsLastIndex = array.GetUpperBound(0);
            var columnsFirstIndex = array.GetLowerBound(1);
            var columnsLastIndex = array.GetUpperBound(1);

            writer.WriteStartArray();
            for (var i = rowsFirstIndex; i <= rowsLastIndex; i++)
            {
                writer.WriteStartArray();
                for (var j = columnsFirstIndex; j <= columnsLastIndex; j++)
                    _valueConverter.WriteOrSerialize(writer, array[i, j], options);
                writer.WriteEndArray();
            }
            writer.WriteEndArray();
        }
        
        public override T [,] Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) =>
            JsonSerializer.Deserialize<List<List<T>>>(ref reader, options)?.To2D();
    }
}

public static partial class ArrayExtensions
{
    public static T[,] To2D<T>(this List<List<T>> source)
    {
        // Adapted from this answer https://stackoverflow.com/a/26291720/3744182
        // By https://stackoverflow.com/users/3909293/diligent-key-presser
        // To https://stackoverflow.com/questions/26291609/converting-jagged-array-to-2d-array-c-sharp
        var firstDim = source.Count;
        var secondDim = source.Select(row => row.Count).FirstOrDefault();
        if (!source.All(row => row.Count == secondDim))
            throw new InvalidOperationException();
        var result = new T[firstDim, secondDim];
        for (var i = 0; i < firstDim; i++)
            for (int j = 0, count = source[i].Count; j < count; j++)
                result[i, j] = source[i][j];
        return result;
    }
}   

public static class JsonSerializerExtensions
{
    public static void WriteOrSerialize<T>(this JsonConverter<T> converter, Utf8JsonWriter writer, T value, JsonSerializerOptions options)
    {
        if (converter != null)
            converter.Write(writer, value, options);
        else
            JsonSerializer.Serialize(writer, value, typeof(T), options);
    }
}

并像这样使用它:

var array1 = new double [,] { {1.1, 1.2, 1.3 }, { 2.1, 2.2, 2.3 } };

var options = new JsonSerializerOptions
{
    Converters = { new Array2DConverter() },
};
var json = JsonSerializer.Serialize(array1, options);
var array2 = JsonSerializer.Deserialize<double [,]>(json, options);

Notes:

  • 虽然需要将整个 JSON 读入中间文件List<List<T>>为了正确计算所需的二维数组外部维度,可以将二维数组直接写入 JSON,而无需转换为中间表示形式。

演示小提琴here https://dotnetfiddle.net/Zb61Sd.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何使用 System.Text.Json 将 double[] 二维数组序列化为 JSON? 的相关文章

随机推荐