I use JsonFX to serialize an instance to json, and I need to ignore some attributes and preprocess others. How do I do that ? The doc is not very clear on that.
My class looks a bit like this one :
public class Primitive{
public string type;
public float[] vertices;
public int[] indices;
public int[] edgeIndices;
public Scene scene;
When outputting json, I need to ignore the scene
attribute (that's the whole 3d scene) and to pre-process the vertices
, indices
, edgeIndices
using some compression scheme.
And, obviously, I need the symmetrical operation when receiving json.
But how ?
You can use [JsonIgnore]
along with 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
}
}
Or, you can use data contract attributes along with 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
}
}
(Note however that DataContractResolverStrategy
is broken in .Net 3.5., so you can't use it if you're stuck on that old version.)
Update
One way to "transform" properties during serialization is to use proxy properties, for instance:
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();
}
}
Then write and read like so:
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));