존재하지 않을 수있는 JToken에서 가치 얻기 (모범 사례)


117

Json.NET을 사용하여 C #에 존재하지 않을 수도있는 JSON 값을 검색하는 가장 좋은 방법은 무엇입니까 ?

지금은 때때로 특정 키 / 값 쌍을 포함하고 때로는 포함하지 않는 JSON을 반환하는 JSON 공급자를 다루고 있습니다. 나는 내 값을 얻기 위해 (아마도 잘못되었을 수도 있음)이 방법을 사용하고 있습니다 (더블을 얻는 예).

if(null != jToken["width"])
    width = double.Parse(jToken["width"].ToString());
else
    width = 100;

이제는 잘 작동하지만 많은 경우 번거 롭습니다. 결국 확장 메서드 작성하고 나서야 멍청한 것인지 궁금합니다 ... 어쨌든 여기에 확장 메서드가 있습니다. 더):

public static T GetValue<T>(this JToken jToken, string key,
                            T defaultValue = default(T))
{
    T returnValue = defaultValue;

    if (jToken[key] != null)
    {
        object data = null;
        string sData = jToken[key].ToString();

        Type type = typeof(T);

        if (type is double)
            data = double.Parse(sData);
        else if (type is string)
            data = sData;

        if (null == data && type.IsValueType)
            throw new ArgumentException("Cannot parse type \"" + 
                type.FullName + "\" from value \"" + sData + "\"");

        returnValue = (T)Convert.ChangeType(data, 
            type, CultureInfo.InvariantCulture);
    }

    return returnValue;
}

다음은 확장 메서드를 사용하는 예입니다.

width = jToken.GetValue<double>("width", 100);

BTW, 정말 멍청한 질문이 될 수있는 것을 용서해주세요. 기능이 내장되어 있어야 할 것 같기 때문입니다. 저는 Google 및 Json.NET 문서를 사용해 보았지만 해결책을 찾는 데 무능합니다. 내 질문 또는 문서에 명확하지 않습니다.


나는 조금 늦게 알아,하지만 당신은이 단순화 된 버전을 시도 할 수 있습니다 GetValue아래
LB

답변:


210

이것은 제네릭 메서드의 Value()용도입니다. nullable 값 유형 및 ??연산자 와 결합하면 원하는 동작을 정확하게 얻을 수 있습니다 .

width = jToken.Value<double?>("width") ?? 100;

4
확장 방법입니다.
Dave Van den Eynde 2013 년

2
@PaulHazen, 그다지 나쁘지 않습니다 ... 당신은 방금 바퀴를 약간 재창조했습니다.
devinbost

"폭"json으로 존재하지 않고 JToken가 null의 경우이 작동하지 않습니다
디팍

2
@Deepak "width"가 없으면 작동합니다. 물론 경우는 일을하지 않는 jToken것입니다 null,하지만 그건 문제가 무엇을 요구하지 않습니다. null 조건부 연산자를 사용하여 쉽게 수정할 수 있습니다 width = jToken?.Value<double?>("width") ?? 100;.
svick

1
JToken.Value<T>JToken이 JValue 인 경우 예외를 throw합니다.
Kyle Delaney

22

나는 GetValue아래와 같이 쓸 것이다

public static T GetValue<T>(this JToken jToken, string key, T defaultValue = default(T))
{
    dynamic ret = jToken[key];
    if (ret == null) return defaultValue;
    if (ret is JObject) return JsonConvert.DeserializeObject<T>(ret.ToString());
    return (T)ret;
}

이렇게하면 기본 유형뿐만 아니라 복잡한 개체의 값도 얻을 수 있습니다. 다음은 샘플입니다.

public class ClassA
{
    public int I;
    public double D;
    public ClassB ClassB;
}
public class ClassB
{
    public int I;
    public string S;
}

var jt = JToken.Parse("{ I:1, D:3.5, ClassB:{I:2, S:'test'} }");

int i1 = jt.GetValue<int>("I");
double d1 = jt.GetValue<double>("D");
ClassB b = jt.GetValue<ClassB>("ClassB");

꽤 멋지지만 단순한 데이터 유형 만 얻을 수 있다는 우려의 분리가 마음에 듭니다. JSON 파싱에 관해서는 분리 개념이 약간 모호하지만. 관찰자 / 관찰 가능 모델 (mvvm 포함)을 구현하기 때문에 모든 구문 분석을 한곳에 유지하고 단순하게 유지하는 경향이 있습니다 (그 중 일부는 나에게 반환되는 데이터의 예측 불가능 성이기도합니다).
Paul Hazen

@PaulHazen 나는 당신을 이해한다고 말할 수 없습니다. 귀하의 질문은 retrieving JSON values that may not even exist내가 제안한 모든 것이 귀하의 GetValue방법 을 변경하는 것 입니다. 나는 당신이 원하는 방식으로 작동합니다 생각
LB

이번에는 좀 더 명확 해 지길 바랍니다. 귀하의 방법은 훌륭하게 작동하며 내가 원하는 것을 정확하게 달성합니다. 그러나 내 질문에 설명되지 않은 더 큰 맥락은 내가 작업하고있는 특정 코드가 내가 고도로 양도하기를 원하는 코드라는 것입니다. 메서드가 방해가된다는 것은 논쟁의 여지가 있지만 GetValue <T>에서 개체를 역 직렬화하는 기능을 도입합니다.이 패턴은 더 나은 JSON 파서가있는 플랫폼으로 코드를 이동하기 위해 피하고 싶은 패턴입니다 (예 : , 예를 들어 Win8). 그래서 내가 물은 것에 대해 네, 당신의 코드는 완벽 할 것입니다.
Paul Hazen 2012 년

9

토큰이 있는지 확인하는 방법은 다음과 같습니다.

if (jobject["Result"].SelectToken("Items") != null) { ... }

"결과"에 "항목"이 있는지 확인합니다.

이것은 예외를 발생시키는 작동하지 않는 예입니다.

if (jobject["Result"]["Items"] != null) { ... }

3

당신은 단순히 typecast를 할 수 있고, 그것은 당신을 위해 변환을 할 것입니다.

var with = (double?) jToken[key] ?? 100;

null해당 키가 개체에 없으면 자동으로 반환 되므로 테스트 할 필요가 없습니다.


1

TYPE variable = jsonbody["key"]?.Value<TYPE>() ?? DEFAULT_VALUE;

예 :

bool attachMap = jsonbody["map"]?.Value<bool>() ?? false;


1

이것은 null을 처리합니다.

var body = JObject.Parse("anyjsonString");

body?.SelectToken("path-string-prop")?.ToString();

body?.SelectToken("path-double-prop")?.ToObject<double>();
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.