2009-06-04 3 views
4

С учетом такого объекта:как сериализовать только некоторые свойства объекта

Foo foo = new Foo 
{ 
    A = "a", 
    B = "b", 
    C = "c", 
    D = "d" 
}; 

Как можно сериализации и десериализации только определенные свойства (например А и D).

Original: 
    { A = "a", B = "b", C = "c", D = "d" } 

Serialized: 
    { A = "a", D = "d" } 

Deserialized: 
    { A = "a", B = null, C = null, D = "d" } 

Я написал код, используя JavaScriptSerializer из System.Web.Extensions.dll:

public string Serialize<T>(T obj, Func<T, object> filter) 
{ 
    return new JavaScriptSerializer().Serialize(filter(obj)); 
} 

public T Deserialize<T>(string input) 
{ 
    return new JavaScriptSerializer().Deserialize<T>(input); 
} 

void Test() 
{ 
    var filter = new Func<Foo, object>(o => new { o.A, o.D }); 

    string serialized = Serialize(foo, filter); 
    // {"A":"a","D":"d"} 

    Foo deserialized = Deserialize<Foo>(serialized); 
    // { A = "a", B = null, C = null, D = "d" } 
} 

Но я хотел бы десериализатор работать немного по-другому:

Foo output = new Foo 
{ 
    A = "1", 
    B = "2", 
    C = "3", 
    D = "4" 
}; 

Deserialize(output, serialized); 
// { A = "a", B = "2", C = "3", D = "d" } 

Любой идеи?

Возможно, существуют и другие доступные или существующие альтернативы?

EDIT:

Были некоторые предложения использовать атрибуты, чтобы указать сериализуемые поля. Я ищу более динамичное решение. Так что я могу сериализовать А, В и в следующий раз, C, D.

EDIT 2:

Любые решения сериализация (JSON, XML, Binary, YAML, ...) в порядке.

ответ

4

Я сделал что-то подобное самому с Javascript Serializer в прошлом. В моем случае я хотел только сериализовать свойства с нулевым значением в объекте, содержащем значение. Я сделал это, используя отражение, проверив свойство для значения и добавив свойство в словарь, например.

public static Dictionary<string,object> CollectFilledProperties(object instance) 
{ 
    Dictionary<string,object> filledProperties = new Dictionary<string,object>(); 
    object data = null; 

    PropertyInfo[] properties = instance.GetType().GetProperties(); 
    foreach (PropertyInfo property in properties) 
    { 
     data = property.GetValue(instance, null); 

     if (IsNullable(property.PropertyType) && data == null) 
     { 
      // Nullable fields without a value i.e. (still null) are ignored. 
      continue; 
     } 

     // Filled has data. 
     filledProperties[property.Name] = data; 
    } 

    return filledProperties; 
} 

public static bool IsNullable(Type checkType) 
{ 
    if (checkType.IsGenericType && checkType.GetGenericTypeDefinition() == typeof(Nullable<>)) 
    { 
     // We are a nullable type - yipee. 
     return true; 
    } 
    return false; 
} 

Затем вместо сериализации исходного объекта вы передаете словарь и bob's ваш дядя.

3

Есть атрибуты, которые могут быть применены к классам и/или свойствам, которые управляют сериализацией. Attributes that control serialization.

23

Довольно легко - просто украсьте методы, которые вы хотите игнорировать, с атрибутом [ScriptIgnore].

+0

Я бы хотел, чтобы он был более динамичным. Поэтому я могу сериализовать либо A, B, либо C, D. – alex2k8

+4

Тогда вы смотрите на это с неправильного угла - нативная сериализация - это сериализация объектов. Вероятно, лучшим вариантом было бы создать два объекта - один для A и B, один для C и D, а затем сериализовать любой из них по мере необходимости. –

1

Что касается тега атрибута "[NonSerialized()]?

class Foo 
    { 
     field A; 

     [NonSerialized()] 
     field B; 

     [NonSerialized()] 
     field C; 

     field D; 
    } 
+1

Это работает для двоичной сериализации. Приведенный пример - сериализация Java-скрипта. Я не уверен, что это сработает. – JaredPar

+6

Эквивалентным атрибутом JavaScriptSerializer является [ScriptIgnore()]. – LorenzCK

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