Получить значение из JToken, которое может не существовать (лучшие практики)
каков наилучший способ получения значений JSON, которые могут даже не существовать в C# с помощью Json.NET?
сейчас я имею дело с поставщиком JSON, который возвращает JSON, который иногда содержит определенные пары ключ/значение, а иногда и нет. Я использую (возможно, неправильно) этот метод, чтобы получить мои значения (пример для получения двойного):
if(null != jToken["width"])
width = double.Parse(jToken["width"].ToString());
else
width = 100;
Теперь это работает нормально, но когда их много, это громоздко. Я закончил писать метод расширения, и только после написав это, я задался вопросом, может быть, я был глуп... в любом случае, вот метод расширения (я включаю только случаи для double и string, но на самом деле у меня есть еще несколько):
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);
кстати, пожалуйста, простите, что может быть действительно глупым вопросом, так как кажется, что-то должно быть встроено в функцию... Я попробовал Google, и Json.NET документация, однако я либо не умею находить решение моего вопроса, либо это не ясно в документации.
6 ответов:
Это в значительной степени то, что общий метод
Value()
для. Вы получаете именно то поведение, которое вы хотите, если вы объедините его с типами значений nullable и??
оператор:width = jToken.Value<double?>("width") ?? 100;
Я бы написал
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");
вот как вы можете проверить, существует ли токен:
if (jobject["Result"].SelectToken("Items") != null) { ... }
Он проверяет, существует ли" элементы "в"результате".
это не рабочий пример, который вызывает исключение:
if (jobject["Result"]["Items"] != null) { ... }
Вы можете просто набирать, и он будет делать преобразование для вас, например
var with = (double?) jToken[key] ?? 100;
он автоматически вернется
null
если указанный ключ отсутствует в объекте, поэтому нет необходимости проверять его.