JToken (또는 문자열)을 주어진 유형으로 변환
TL; DR 버전
유형의 객체가 JToken있고 (일 수도 있음 string) type변수에 포함 된 유형으로 변환해야 합니다.
Type type = typeof(DateTime); /* can be any other Type like string, ulong etc */
var obj = jsonObject["date_joined"]; /* contains 2012-08-13T06:01:23Z+05:00 */
var result = Some_Way_To_Convert(type, obj);
위 result의 값은에 제공된 DateTime 객체 여야합니다 date_joined.
전체 이야기
Windows Phone 프로젝트에서 RestSharp와 Json.NET을 모두 사용하고 있으며 REST API에서 JSON 응답을 deserialize하는 동안 멈춰 있습니다.
내가 실제로 달성하려는 것은 이미 RestSharp로 할 수있는 것처럼 JSON 응답을 내 CLR 엔터티에 쉽게 매핑 할 수있는 일반 메서드를 작성하는 것입니다. 유일한 문제는 기본 RestSharp 구현이 나를 위해 작동하지 않고 응답이 항상 모든 속성을 반환하지 않기 때문에 JSON을 성공적으로 구문 분석하는 데 실패한다는 것입니다 ( nullREST 서버에서 가져온 필드를 반환하지 않음 ).
이것이 제가 Newtonsoft의 Json.NET을 사용하기로 결정한 이유입니다. 훨씬 더 강력한 Json 역 직렬화 엔진이 있기 때문입니다. 불행히도 RestSharp와 같은 퍼지 속성 / 필드 이름을 지원하지 않으므로 (또는 찾지 못함) say와 같은 것을 사용할 때 내 CLR 엔터티에 올바르게 매핑되지 않습니다 JsonConvert.DeserializeObject<User>(response.Content).
내 Json의 모습은 다음과 같습니다 (실제로 예).
{
"id" : 77239923,
"username" : "UzEE",
"email" : "uzee@email.net",
"name" : "Uzair Sajid",
"twitter_screen_name" : "UzEE",
"join_date" : "2012-08-13T05:30:23Z05+00",
"timezone" : 5.5,
"access_token" : {
"token" : "nkjanIUI8983nkSj)*#)(kjb@K",
"scope" : [ "read", "write", "bake pies" ],
"expires" : 57723
},
"friends" : [{
"id" : 2347484",
"name" : "Bruce Wayne"
},
{
"id" : 996236,
"name" : "Clark Kent"
}]
}
다음은 내 CLR 엔터티의 예입니다.
class AccessToken
{
public string Token { get; set; }
public int Expires { get; set; }
public string[] Scope { get; set; }
public string Secret { get; set; } /* may not always be returned */
}
class User
{
public ulong Id { get; set; }
public string UserName { get; set; }
public string Email { get; set; }
public string Name { get; set; }
public string TwitterScreenName { get; set; }
public DateTime JoinDate { get; set; }
public float Timezone { get; set; }
public bool IsOnline { get; set; } /* another field that might be blank e.g. */
public AccessToken AccessToken { get; set; }
public List<User> Friends { get; set; }
}
내가 원하는 것은 위의 JSON을 주어진 CLR 개체로 구문 분석하는 간단한 방법입니다. 나는 RestSharp 소스 코드를 둘러 보았다했습니다과 본 JsonDeserializer코드를 나는 일반적인 확장 방법을 쓸 수있었습니다 DeserializeResponse<T>에 JObject그 유형의 객체를 반환해야합니다 T. 의도 된 용도는 다음과 같습니다.
var user = JObject.Parse(response.Content).DeserializeResponse<User>();
위의 메소드는 사용자 엔티티 객체에 대한 주어진 Json 응답을 구문 분석해야합니다. 다음은 DeserializeResponse<User>확장 메서드 에서 수행중인 작업의 실제 코드 스 니펫입니다 (RestSharp 코드 기반).
public static T DeserializeResponse<T>(this JObject obj) where T : new()
{
T result = new T();
var props = typeof(T).GetProperties().Where(p => p.CanWrite).ToList();
var objectDictionary = obj as IDictionary<string, JToken>;
foreach (var prop in props)
{
var name = prop.Name.GetNameVariants(CultureInfo.CurrentCulture).FirstOrDefault(n => objectDictionary.ContainsKey(n));
var value = name != null ? obj[name] : null;
if (value == null) continue;
var type = prop.PropertyType;
if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>))
{
type = type.GetGenericArguments()[0];
}
// This is a problem. I need a way to convert JToken value into an object of Type type
prop.SetValue(result, ConvertValue(type, value), null);
}
return result;
}
I'm guessing that the conversion should be a really straightforward thing to do since its a trivial task. But I've been searching for a quite a while now and still haven't found a way to do it via Json.NET (and lets be honest, the documentation is kinda though to understand and lacks some examples).
Any help would really be appreciated.
There is a ToObject method now.
var obj = jsonObject["date_joined"];
var result = obj.ToObject<DateTime>();
It also works with any complex type, and obey to JsonPropertyAttribute rules
var result = obj.ToObject<MyClass>();
public class MyClass
{
[JsonProperty("date_field")]
public DateTime MyDate {get;set;}
}
System.Convert.ChangeType(jtoken.ToString(), targetType);
or
JsonConvert.DeserializeObject(jtoken.ToString(), targetType);
--EDIT--
Uzair, Here is a complete example just to show you they work
string json = @"{
""id"" : 77239923,
""username"" : ""UzEE"",
""email"" : ""uzee@email.net"",
""name"" : ""Uzair Sajid"",
""twitter_screen_name"" : ""UzEE"",
""join_date"" : ""2012-08-13T05:30:23Z05+00"",
""timezone"" : 5.5,
""access_token"" : {
""token"" : ""nkjanIUI8983nkSj)*#)(kjb@K"",
""scope"" : [ ""read"", ""write"", ""bake pies"" ],
""expires"" : 57723
},
""friends"" : [{
""id"" : 2347484,
""name"" : ""Bruce Wayne""
},
{
""id"" : 996236,
""name"" : ""Clark Kent""
}]
}";
var obj = (JObject)JsonConvert.DeserializeObject(json);
Type type = typeof(int);
var i1 = System.Convert.ChangeType(obj["id"].ToString(), type);
var i2 = JsonConvert.DeserializeObject(obj["id"].ToString(), type);
var i2 = JsonConvert.DeserializeObject(obj["id"].ToString(), type);
throws a parsing exception due to missing quotes around the first argument (I think). I got it to work by adding the quotes:
var i2 = JsonConvert.DeserializeObject("\"" + obj["id"].ToString() + "\"", type);
I was able to convert using below method for my WebAPI:
[HttpPost]
public HttpResponseMessage Post(dynamic item) // Passing parameter as dynamic
{
JArray itemArray = item["Region"]; // You need to add JSON.NET library
JObject obj = itemArray[0] as JObject; // Converting from JArray to JObject
Region objRegion = obj.ToObject<Region>(); // Converting to Region object
}
참고URL : https://stackoverflow.com/questions/11927135/converting-a-jtoken-or-string-to-a-given-type
'Nice programing' 카테고리의 다른 글
| 쉽고 간단하게 Java에서 LRU 캐시 사용 (0) | 2020.11.23 |
|---|---|
| MySQL select 문에서 조건문을 어떻게 작성합니까? (0) | 2020.11.23 |
| 동일한 모델에서 두 개의 날짜 필드를 비교하는 Django 쿼리 셋 필터를 만드는 방법 (0) | 2020.11.23 |
| Android Google지도 마커 탐색 옵션 사용 중지 (0) | 2020.11.23 |
| 참조로 예외를 포착하는 것이 위험합니까? (0) | 2020.11.23 |