web-dev-qa-db-fra.com

Possible de rechercher une clé qui n'existe pas dans Json.net

Quelques formats différents sont entrés, mais je ne peux pas comprendre comment les gérer tous parce que, lorsque j'essaie de trouver par la clé, json.net plante. J'espérais qu'il reviendrait à null.

foreach (var item in jsonObj)
{
    var msg = item.Value["Msg"];
    if (msg != null)
    {
       txtErrors.Text += msg + Environment.NewLine;
    }
}

// format un

{[UserNotFound, {
  "SeverityType": 3,
  "ValidationType": 2,
  "Msg": "Email Not Found"
}]}

mon code fonctionne.

// format 2 (venu parce que je n'ai pas attrapé d'exception sur serveride)

{
  "Message": "An error has occurred.",
  "ExceptionMessage": "Object reference not set to an instance of an object.",
  "ExceptionType": "System.NullReferenceException",
  "StackTrace": "  "
}

Je peux bien sûr résoudre ce problème et attraper l'exception. Cependant, si j'oublie un jour de plus, je préfère que le client ne se bloque pas non plus. J'adorerais donc simplement imprimer le "message" mais je ne comprends pas comment le faire afin qu'il ne tombe pas en panne sur var msg = item.Value["Msg"];

L'erreur que je reçois quand il essaie de faire var msg = item.Value["Msg"];

System.InvalidOperationException was unhandled
  Message=Cannot access child value on Newtonsoft.Json.Linq.JValue.
  StackTrace:
       at Newtonsoft.Json.Linq.JToken.get_Item(Object key)
       at Fitness.WindowsPhone7.UI.MainPage.<btnSignIn_Click>b__0(IRestResponse response)
       at RestSharp.RestClientExtensions.<>c__DisplayClass1.<ExecuteAsync>b__0(IRestResponse response, RestRequestAsyncHandle handle)
       at RestSharp.RestClient.ProcessResponse(IRestRequest request, HttpResponse httpResponse, RestRequestAsyncHandle asyncHandle, Action`2 callback)
       at RestSharp.RestClient.<>c__DisplayClass3.<ExecuteAsync>b__0(HttpResponse r)
       at RestSharp.RestClient.<>c__DisplayClass5.<>c__DisplayClass7.<ExecuteAsync>b__2(Object s)
       at System.Reflection.RuntimeMethodInfo.InternalInvoke(RuntimeMethodInfo rtmi, Object obj, BindingFlags invokeAttr, Binder binder, Object parameters, CultureInfo culture, Boolean isBinderDefault, Assembly caller, Boolean verifyAccess, StackCrawlMark& stackMark)
       at System.Reflection.RuntimeMethodInfo.InternalInvoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture, StackCrawlMark& stackMark)
       at System.Reflection.MethodBase.Invoke(Object obj, Object[] parameters)
       at System.Delegate.DynamicInvokeOne(Object[] args)
       at System.MulticastDelegate.DynamicInvokeImpl(Object[] args)
       at System.Delegate.DynamicInvoke(Object[] args)
       at System.Windows.Threading.DispatcherOperation.Invoke()
       at System.Windows.Threading.Dispatcher.Dispatch(DispatcherPriority priority)
       at System.Windows.Threading.Dispatcher.OnInvoke(Object context)
       at System.Windows.Hosting.CallbackCookie.Invoke(Object[] args)
       at System.Windows.Hosting.DelegateWrapper.InternalInvoke(Object[] args)
       at System.Windows.RuntimeHost.ManagedHost.InvokeDelegate(IntPtr pHandle, Int32 nParamCount, ScriptParam[] pParams, ScriptParam& pResult)
17
chobo2

En supposant que vous utilisiez Newtonsoft.Json:

Vous pouvez utiliser JObject pour tester s’il existe une propriété ou non:

JObject jObj; //initialized somewhere, perhaps in your foreach
var msgProperty = jObj.Property("msg");

//check if property exists
if (msgProperty != null) {
    var mag = msgProperty.Value;
} else {
    //there is no "msg" property, compensate somehow.
}
34
Alexey Raga

Vous pouvez utiliser TryGetValue, c'est une méthode standard pour faire exactement ce dont vous avez besoin. Je dis standard parce que les méthodes Try peuvent être trouvées tout autour du framework .NET et ont généralement toujours la même signature de méthode.

En utilisant cela, vous pouvez obtenir une valeur comme celle-ci.

JObject json = new JObject();
JToken value;
if (json.TryGetValue("myProperty", out value))
{
    string finalValue = (string)value;
}

TryGetValue renvoie un booléen indiquant si la valeur a été trouvée ou non. Si la valeur est trouvée, la valeur transmise en tant que second paramètre est définie sur la valeur de la propriété. Sinon, est défini sur null.

4
Fabio Marcolini

Ou vous pouvez simplement utiliser le ContainsKey sur un JsonObject . Voici un exemple de mon propre code avec un problème similaire au vôtre:

foreach (JsonObject feed in data)
            {
                var fbFeed = new FacebookFeeds();
                if (feed.ContainsKey("message"))
                    fbFeed.Message = (string)feed["message"];
                if (feed.ContainsKey("story"))
                    fbFeed.Message = (string)feed["story"];
                if (feed.ContainsKey("picture"))
                    fbFeed.Message = (string)feed["picture"];
                fbFeeds.Add(fbFeed);
            }
0
Ben