내 응용 프로그램에서 JSON.NET을 사용하여 객체를 json으로 직렬화 / 역 직렬화해야합니다. 객체에는 문자열 배열을 포함하는 ArrayList의 속성 유형이 있습니다. 이를 시뮬레이션하기 위해 다음 단위 테스트를 작성했습니다.
public class JsonTests
{
public class MyTestClass
{
public ArrayList Items { get; private set; }
public MyTestClass()
{
this.Items = new ArrayList();
}
}
[Fact]
public void JsonConvert_Should_Serialize_ArrayList_And_Deserialize_Successfully()
{
MyTestClass myObject = new MyTestClass();
myObject.Items.Add(new string[] { "Test1", "Test2" });
string jsonResult = JsonConvert.SerializeObject(myObject);
MyTestClass tempMyObject = JsonConvert.DeserializeObject<MyTestClass>(jsonResult);
//(tempMyObject.Items[0] as string[]) casts to null therefore it throws exception
Assert.Equal((myObject.Items[0] as string[])[0], (tempMyObject.Items[0] as string[])[0]);
}
}
예외 기간 직렬화는 발생하지 않습니다. 그러나 ArrayList를 제대로 deserialize하지 않습니다.
내 질문은 어떻게 문자열 배열의 ArrayList로 다시 역 직렬화 할 수 있습니까?
업데이트 : 또한 클래스 정의를 변경할 수 없습니다. 클래스를 편집 할 수없는 어셈블리에서 클래스가 구현되었습니다.
ArrayList
유형이 지정되지 않은 일반 컬렉션이 아니므로 Json.NET에 예상 항목 유형을 알려야합니다. 이를 수행하는 한 가지 방법은에 대한 사용자 지정JsonConverter
을 사용하는 것입니다 ArrayList
.
public class ArrayListConverter<TItem> : JsonConverter
{
public override bool CanWrite { get { return false; } }
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.Null)
return null;
var list = serializer.Deserialize<List<TItem>>(reader);
var arrayList = existingValue as ArrayList ?? new ArrayList(list.Count);
arrayList.AddRange(list);
return arrayList;
}
public override bool CanConvert(Type objectType)
{
return objectType == typeof(ArrayList);
}
}
그런 다음 다음과 같이 변환기를 클래스에 적용하십시오.
public class MyTestClass
{
[JsonConverter(typeof(ArrayListConverter<string []>))]
public ArrayList Items { get; private set; }
public MyTestClass()
{
this.Items = new ArrayList();
}
}
샘플 바이올린 .
클래스를 수정할 수없고 개체 그래프 의 모든 인스턴스 가 ArrayList
항목을로 역 직렬화하도록 string []
하려면 변환기를 JsonSerializerSettings.Converters
형식에 추가하는 대신에 추가 할 수 있습니다 .
var tempMyObject = JsonConvert.DeserializeObject<MyTestClass>(jsonResult,
new JsonSerializerSettings { Converters = { new ArrayListConverter<string []>() } });
샘플 바이올린 # 2 .
마지막으로, 클래스를 수정할 수없고 ArrayList Items
내부 의 특정 속성 만 MyTestClass
해당 항목이으로 역 직렬화되도록 string []
하려면 .NET 용 사용자 지정 변환기를 만들어야합니다 MyTestClass
. json.NET 이있는 일부 필드에 대해서만 Custom deserializer 의 패턴을 사용하여 ArrayList
속성 을 사용자 지정 역 직렬화 하고 나머지는 기본 역 직렬화 로 채울 수 있습니다 .
public class MyTestClassConverter : JsonConverter
{
public override bool CanWrite { get { return false; } }
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.Null)
return null;
var root = existingValue as MyTestClass ?? (MyTestClass)serializer.ContractResolver.ResolveContract(objectType).DefaultCreator();
var jsonObject = JObject.Load(reader);
var jsonItems = jsonObject["Items"].RemoveFromLowestPossibleParent();
if (jsonItems != null && jsonItems.Type != JTokenType.Null)
{
root.Items.AddRange(jsonItems.ToObject<List<string []>>());
}
// Populate the remaining standard properties
using (var subReader = jsonObject.CreateReader())
{
serializer.Populate(subReader, root);
}
return root;
}
public override bool CanConvert(Type objectType)
{
return typeof(MyTestClass).IsAssignableFrom(objectType);
}
}
public static class JsonExtensions
{
public static JToken RemoveFromLowestPossibleParent(this JToken node)
{
if (node == null)
return null;
var contained = node.AncestorsAndSelf().Where(t => t.Parent is JContainer && t.Parent.Type != JTokenType.Property).FirstOrDefault();
if (contained != null)
contained.Remove();
// Also detach the node from its immediate containing property -- Remove() does not do this even though it seems like it should
if (node.Parent is JProperty)
((JProperty)node.Parent).Value = null;
return node;
}
}
그런 다음 다음과 같이 사용하십시오.
var tempMyObject = JsonConvert.DeserializeObject<MyTestClass>(jsonResult,
new JsonSerializerSettings { Converters = { new MyTestClassConverter() } });
샘플 바이올린 # 3 .
이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.
침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제
몇 마디 만하겠습니다