반응형
Json을 사용하여 이종 JSON 어레이를 공변량 목록으로 역직렬화 <>.그물
JSON-array에는 다른 속성을 가진 다른 유형의 개체가 포함되어 있습니다.속성 중 하나를 "type"이라고 하며 배열 항목의 유형을 결정합니다.다음은 데이터의 예입니다.
[{
type : "comment",
text : "xxxx"
}, {
type : "code",
tokens : [{
type : "ref",
data : "m"
}, {
type : "operator",
data : "e"
}
]
}, {
type : "for",
boundLocal : {
type : "local",
name : "i",
kind : "Number"
},
upperBound : {
type : "ref",
tokens : [{
type : "operator",
data : "3"
}, {
type : "operator",
data : "0"
}
]
},
body : [{
type : "code",
tokens : [{
type : "ref",
data : "x"
}
]
}, {
type : "code",
tokens : [{
type : "ref",
data : "y"
}
}
]
]
]
이러한 오브젝트를 에 매핑합니다.넷 실장 1개의 기본 클래스와 여러 개의 자식 클래스(복잡한 계층, 4개의 "세대"가 있음)의 일련의 클래스를 정의합니다.이러한 클래스의 간단한 예를 다음에 나타냅니다.
public abstract class TExpression
{
[JsonProperty("type")]
public string Type { get; set; }
}
public class TComment : TExpression
{
[JsonProperty("text")]
public string Text { get; set; }
}
public class TTokenSequence : TExpression
{
[JsonProperty("tokens")]
public List<TToken> Tokens { get; set; }
}
이 배열을 다음과 같이 선언된 공변 일반 목록으로 역직렬화할 수 있어야 합니다.
List<TExpression> myexpressions = JsonConvert.DeserializeObject<List<TExpression>>(aststring);
이 목록에는 TExpression에서 상속되는 적절한 자식 클래스의 인스턴스가 포함되어 있어야 합니다.그러면 코드 후반부에서 다음 코드를 사용할 수 있습니다.
foreach(TExpression t in myexpressions)
{
if (t is TComment) dosomething;
if (t is TTokenSequence) dosomethingelse;
}
JSON을 사용하여 어떻게 접속합니까?인터넷?
다음은 Custom Creation Converter를 사용하는 예입니다.
public class JsonItemConverter : Newtonsoft.Json.Converters.CustomCreationConverter<Item>
{
public override Item Create(Type objectType)
{
throw new NotImplementedException();
}
public Item Create(Type objectType, JObject jObject)
{
var type = (string)jObject.Property("valueType");
switch (type)
{
case "int":
return new IntItem();
case "string":
return new StringItem();
}
throw new ApplicationException(String.Format("The given vehicle type {0} is not supported!", type));
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
// Load JObject from stream
JObject jObject = JObject.Load(reader);
// Create target object based on JObject
var target = Create(objectType, jObject);
// Populate the object properties
serializer.Populate(jObject.CreateReader(), target);
return target;
}
}
public abstract class Item
{
public string ValueType { get; set; }
[JsonProperty("valueTypeId")]
public int ValueTypeId { get; set; }
[JsonProperty("name")]
public string Name { get; set; }
public new virtual string ToString() { return "Base object, we dont' want base created ValueType=" + this.ValueType + "; " + "name: " + Name; }
}
public class StringItem : Item
{
[JsonProperty("value")]
public string Value { get; set; }
[JsonProperty("numberChars")]
public int NumberCharacters { get; set; }
public override string ToString() { return "StringItem object ValueType=" + this.ValueType + ", Value=" + this.Value + "; " + "Num Chars= " + NumberCharacters; }
}
public class IntItem : Item
{
[JsonProperty("value")]
public int Value { get; set; }
public override string ToString() { return "IntItem object ValueType=" + this.ValueType + ", Value=" + this.Value; }
}
class Program
{
static void Main(string[] args)
{
// json string
var json = "[{\"value\":5,\"valueType\":\"int\",\"valueTypeId\":1,\"name\":\"numberOfDups\"},{\"value\":\"some thing\",\"valueType\":\"string\",\"valueTypeId\":1,\"name\":\"a\",\"numberChars\":11},{\"value\":2,\"valueType\":\"int\",\"valueTypeId\":2,\"name\":\"b\"}]";
// The above is deserialized into a list of Items, instead of a hetrogenous list of
// IntItem and StringItem
var result = JsonConvert.DeserializeObject<List<Item>>(json, new JsonItemConverter());
foreach (var r in result)
{
// r is an instance of Item not StringItem or IntItem
Console.WriteLine("got " + r.ToString());
}
}
}
JsonSubTypes 라이브러리를 사용하여 선언적인 방법으로 구현할 수도 있습니다.
[JsonConverter(typeof(JsonSubtypes), "valueType")]
[JsonSubtypes.KnownSubType(typeof(IntItem), "int")]
[JsonSubtypes.KnownSubType(typeof(StringItem), "string")]
public abstract class Item
{
public string ValueType { get; set; }
[JsonProperty("valueTypeId")]
public int ValueTypeId { get; set; }
[JsonProperty("name")]
public string Name { get; set; }
public override string ToString()
{
return "Base object, we dont' want base created ValueType=" + this.ValueType + "; " + "name: " + Name;
}
}
public class StringItem : Item
{
[JsonProperty("value")]
public string Value { get; set; }
[JsonProperty("numberChars")]
public int NumberCharacters { get; set; }
public override string ToString()
{
return "StringItem object ValueType=" + this.ValueType + ", Value=" + this.Value + "; " +
"Num Chars= " + NumberCharacters;
}
}
public class IntItem : Item
{
[JsonProperty("value")]
public int Value { get; set; }
public override string ToString()
{
return "IntItem object ValueType=" + this.ValueType + ", Value=" + this.Value;
}
}
[TestMethod]
public void Demo()
{
// json string
var json =
"[{\"value\":5,\"valueType\":\"int\",\"valueTypeId\":1,\"name\":\"numberOfDups\"}," +
"{\"value\":\"some thing\",\"valueType\":\"string\",\"valueTypeId\":1,\"name\":\"a\",\"numberChars\":11}," +
"{\"value\":2,\"valueType\":\"int\",\"valueTypeId\":2,\"name\":\"b\"}]";
var result = JsonConvert.DeserializeObject<List<Item>>(json);
Assert.AreEqual("IntItem object ValueType=int, Value=5", result[0].ToString());
Assert.AreEqual("StringItem object ValueType=string, Value=some thing; Num Chars= 11", result[1].ToString());
Assert.AreEqual("IntItem object ValueType=int, Value=2", result[2].ToString());
}
Custom Creation Converter가 이를 처리할 수 있어야 합니다.
언급URL : https://stackoverflow.com/questions/8241392/deserializing-heterogenous-json-array-into-covariant-list-using-json-net
반응형
'sourcecode' 카테고리의 다른 글
Oracle 사용자와 스키마의 차이점 (0) | 2023.03.05 |
---|---|
credentials를 사용한Http 요청은 무엇이며 왜 사용하는가? (0) | 2023.03.05 |
빈 등록 httpSessionManager가 중복되어 Spring Boot 2.1에서 Keycloak을 사용할 수 없습니다. (0) | 2023.03.05 |
AngularJS 지시 다이내믹 템플릿 (0) | 2023.03.05 |
같은 스테이트먼트에서 입력과 집약을 어떻게 사용하는가? (0) | 2023.03.05 |