2017-10-12 1 views
2

일반 형식 Container<IContentType> 여기서 인터페이스 IContentType은 구체 ContentX 유형 중 하나 일 수 있습니다.일반 형식 비 직렬화

나는 직렬화 모든 것이 괜찮습니다.

Newtonsoft를 사용하여 비 직렬화 할 때 나는 사용자 정의 형식 변환기와 var model = JsonConvert.DeserializeObject<Container<ContentA>>(json, settings)을 사용합니다. 디버거에 내가 Container<ContentA> 개체가 있음을 보여줍니다.

내 계획은 네 가지 가능한 각각의 ContentX 유형에 대해 직렬화를 시도하고 올바른 것을 "추측"할 때까지 자동으로 예외를 잡기 위해 비 직렬화 할 때였습니다. 내가 그렇게 같은 방법 내에서이 작업을 수행 할 경우

그러나 :

public static Container<IContentType> Deserialize(jsonfile) 
{ 
    ... 
    var model = JsonConvert.DeserializeObject<Container<ContentA>>(json, settings) 
    return model; 
} 

나는 "암시 Container<IContentType>Container<ContentA>을 변환 할 수 없습니다"얻을. ContentAIContentType을 구현합니다.

캐스트 연산자, 변환, 동적 또는 암시 적 변환 작업을 만들 수있는 방법이 있습니까?

+0

왜 단지 Container 으로'JsonConvert.DeserializeObject > (json, settings)이 아닌가? –

+0

분산 문제가 발생했습니다. 예를 들어'List '을'List '에''string'이'object'의 서브 클래스 인 경우에도 캐스트 할 수 없습니다. 왜냐하면'List '참조는'Add (Object)'메소드를 가지기 때문입니다. 참조가 가리키는 "List "에 대해서는 유효하지 않습니다. // : –

+2

당신은 [? 기본 클래스 개체의 목록을 역 직렬화하는 JSON.NET에서 사용자 정의 JsonConverter을 구현하는 방법] (HTTPS의 라인을 따라 올바른 구체적인 유형을 유추 사용자 정의'IContentType''에 대한 JsonConverter'을 만들어야합니다 "[json.net을 사용하여 유형 정보없이 다형성 json 클래스를 비 직렬화] (https://stackoverflow.com/q/19307752/3744182) 또는 [다형성 자식이있는 유형의 Json.Net 직렬화] (https://stackoverflow.com/q/19307752/3744182) 개체] (https://stackoverflow.com/q/29528648/3744182). 그러면'Container '으로 deserialize 할 수있다. – dbc

답변

2

오히려 구체적인 유형 (들) X에 대한 Container<ContentX>로 역 직렬화하는 것보다, 당신은 JToken에 JSON을 사전로드 How to implement custom JsonConverter in JSON.NET to deserialize a List of base class objects? 또는 Deserializing polymorphic json classes without type information using json.net의 라인을 따라 구체적인 유형을 유추하는 custom JsonConverter 사용하여 Container<IContentType>로 역 직렬화한다 또는 Json.Net Serialization of Type with Polymorphic Child Object.

따라서 같은 것을 보일 것이다 당신의 계산기 :

public class ContentConverter : JsonConverter 
{ 
    public override bool CanConvert(Type objectType) 
    { 
     return objectType == typeof(IContentType); 
    } 

    Type GetConcreteType(JObject obj) 
    { 
     if (obj.GetValue(nameof(ContentA.SomePropertyOfContentA), StringComparison.OrdinalIgnoreCase) != null) 
      return typeof(ContentA); 
     // Add other tests for other content types. 
     // Return a default type or throw an exception if a unique type cannot be found. 
     throw new JsonSerializationException("Cannot determine concrete type for IContentType"); 
    } 

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) 
    { 
     if (reader.TokenType == JsonToken.Null) 
      return null; 
     var obj = JObject.Load(reader); 
     var concreteType = GetConcreteType(obj); 
     return obj.ToObject(concreteType, serializer); 
    } 

    public override bool CanWrite { get { return false; } } 

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) 
    { 
     throw new NotImplementedException(); 
    } 
} 

그리고 JsonConvert로 호출과 같습니다 마지막으로

var settings = new JsonSerializerSettings 
{ 
    Converters = { new ContentConverter() }, 
}; 
var model = JsonConvert.DeserializeObject<Container<IContentType>>(json, settings); 

, 당신은 사용 유형 완전히 자동으로를 선택할 수 있습니다

new JsonDerivedTypeConverer<IContentType>(typeof(ContentA), typeof(ContentB), typeof(ContentC), typeof(ContentD)) 

여기서 JsonDerivedTypeConverer<T>JsonConverter with Interface에서 가져온 것입니다.