2015-09-25 4 views
0

Я использую JsonFX для сериализации экземпляра json, и мне нужно игнорировать некоторые атрибуты и препроизводить другие. Как мне это сделать ? Док не очень ясен.Как фильтровать/преобразовывать атрибуты объектов для сериализации с помощью jsonfx?

Мой класс выглядит как этот:

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

При выводе JSON, мне нужно игнорировать атрибут scene (это вся 3d сцена) и предварительно процесса в vertices, indices, edgeIndices с использованием некоторая схема сжатия.

И, очевидно, мне нужна симметричная операция при приеме json.

Но как?

ответ

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 
    } 
} 

Или, вы можете использовать data contract attributes вместе с 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)); 
+0

спасибо, но вы охватывают только половину вопроса, как указать предварительное преобразование для значения атрибута? в моем примере вершины изначально являются 'float []', я хочу сжать его, тогда результат будет 'string'. – LBarret

+0

Спасибо, это именно то, что мне нужно. Я не понимал, что для преобразования и игнорирования потребуется два разных подхода. Я совершенно новичок в мире C#. – LBarret

Смежные вопросы