0

我使用 JsonFX 将实例序列化为 json,我需要忽略一些属性并预处理其他属性。我怎么做 ?文档对此不是很清楚。

我的课看起来有点像这个:

public class Primitive{
    public string type;
    public float[] vertices;
    public int[] indices;
    public int[] edgeIndices;
    public Scene scene;

输出 json 时,我需要忽略属性(即整个 3d 场景)并使用一些压缩方案对,进行scene预处理。verticesindicesedgeIndices

而且,很明显,我在接收json时需要对称操作。

但是如何?

4

1 回答 1

2

您可以[JsonIgnore]使用JsonResolverStrategy

public class Scene
{
    public string Name { get; set; } // Or whatever
}

public class Primitive
{
    public string type;
    public float[] vertices;
    public int[] indices;
    public int[] edgeIndices;
    [JsonFx.Json.JsonIgnore]
    public Scene scene;
}

public class TestClass
{
    public static void Test()
    {
        var primitive = new Primitive
        {
            type = "some type",
            vertices = new[] { 1.0f, 2.0f },
            indices = new[] { 1, 2 },
            edgeIndices = new[] { 0, 1 },
            scene = new Scene { Name = "Should Not Be Serialized" }
        };

        var writer = new JsonWriter(new DataWriterSettings(new JsonResolverStrategy()));

        var json = writer.Write(primitive);

        Debug.WriteLine(json);  // Prints {"type":"some type","vertices":[1,2],"indices":[1,2],"edgeIndices":[0,1]}
        Debug.Assert(!json.Contains("Should Not Be Serialized")); // No assert
    }
}

或者,您可以使用数据协定属性以及DataContractResolverStrategy

public class Scene
{
    public string Name { get; set; } // Or whatever
}

[DataContract]
public class Primitive
{
    [DataMember]
    public string type;
    [DataMember]
    public float[] vertices;
    [DataMember]
    public int[] indices;
    [DataMember]
    public int[] edgeIndices;
    [IgnoreDataMember]
    public Scene scene;
}

public class TestClass
{
    public static void Test()
    {
        var primitive = new Primitive
        {
            type = "some type",
            vertices = new[] { 1.0f, 2.0f },
            indices = new[] { 1, 2 },
            edgeIndices = new[] { 0, 1 },
            scene = new Scene { Name = "Should Not Be Serialized" }
        };

        var writer = new JsonWriter(new DataWriterSettings(new DataContractResolverStrategy()));

        var json = writer.Write(primitive);

        Debug.WriteLine(json);
        Debug.Assert(!json.Contains("Should Not Be Serialized")); // No assert
    }
}

(但请注意DataContractResolverStrategy,.Net 3.5 中已损坏,因此如果您停留在旧版本上,则无法使用它。)

更新

在序列化期间“转换”属性的一种方法是使用代理属性,例如:

public class Primitive
{
    public string type;

    public float[] vertices;

    [JsonFx.Json.JsonIgnore]
    public int[] indices;

    [JsonFx.Json.JsonName("indices")]
    public string compressedIndices
    {
        get
        {
            return indices.Base64Compress();
        }
        set
        {
            indices = CompressionExtensions.Base64DecompressIntArray(value);
        }
    }

    public int[] edgeIndices;

    [JsonFx.Json.JsonIgnore]
    public Scene scene;
}

public static class CompressionExtensions
{
    public static string Base64Compress(this IEnumerable<int> values)
    {
        if (values == null)
            return null;
        using (var stream = new MemoryStream())
        {
            using (var compressor = new DeflateStream(stream, CompressionMode.Compress, true))
            {
                var _buffer = new byte[4];
                foreach (var value in values)
                {
                    _buffer[0] = (byte)value;
                    _buffer[1] = (byte)(value >> 8);
                    _buffer[2] = (byte)(value >> 16);
                    _buffer[3] = (byte)(value >> 24);
                    compressor.Write(_buffer, 0, 4);
                }
            }
            return Convert.ToBase64String(stream.GetBuffer(), 0, checked((int)stream.Length)); // Throw an exception on overflow.
        }
    }

    public static int[] Base64DecompressIntArray(string base64)
    {
        if (base64 == null)
            return null;
        var list = new List<int>();
        var m_buffer = new byte[4];
        using (var stream = new MemoryStream(Convert.FromBase64String(base64)))
        {
            using (var compressor = new DeflateStream(stream, CompressionMode.Decompress))
            {
                while (compressor.Read(m_buffer, 0, 4) == 4)
                {
                    list.Add((int)(m_buffer[0] | m_buffer[1] << 8 | m_buffer[2] << 16 | m_buffer[3] << 24));
                }
            }
        }
        return list.ToArray();
    }
}

然后像这样写和读:

        var primitive = new Primitive
        {
            type = "some type",
            vertices = new[] { 1.0f, 2.0f },
            indices = Enumerable.Range(0, 10000).Select(i => 0).ToArray(),
            edgeIndices = new[] { 0, 1 },
            scene = new Scene { Name = "Should Not Be Serialized" }
        };

        var writer = new JsonWriter(new DataWriterSettings(new JsonResolverStrategy()));

        var json = writer.Write(primitive);

        var reader = new JsonReader(new DataReaderSettings(new JsonResolverStrategy()));
        var primitiveBack = reader.Read<Primitive>(json);

        Debug.Assert(primitiveBack.indices.SequenceEqual(primitive.indices));
于 2015-09-25T18:56:13.833 回答