0

I've been having trouble figuring out why this exception is being thrown by JsonConvert.DeserializeObject(). It happens in my ReadJwt() method. I've also included my CreateJwt() method here, just in case, but I can't see any syntax errors in the JSON string it generates.

public static string CreateJwt(TokenObject input) {
    string key = "This key is fake";
    string json = JsonConvert.SerializeObject(input, Formatting.Indented);
    string jwt = JsonWebToken.Encode(json, key, JwtHashAlgorithm.HS256);
    return jwt;
}

public static TokenObject ReadJwt(string jwt) {
    string key = "This key is fake";
    return JsonConvert.DeserializeObject<TokenObject>
        (JsonWebToken.Decode(jwt, key));
}

Here's the exception:

An exception of type 'Newtonsoft.Json.JsonSerializationException' occurred in Newtonsoft.Json.dll but was not handled in user code

Additional information: Error converting value "{

  "id": 8,

  "användarnamn": "test123",

  "utgång": "2017-03-19T19:28:00.5493447Z"

}" to type 'System.Collections.Generic.Dictionary`2[System.String,System.Object]'. Path '', line 1, position 110.

The InnerException is as follows:

Could not cast or convert from System.String to System.Collections.Generic.Dictionary`2[System.String,System.Object].

I've looked at answers to similar questions, but nothing seems helpful to my case. Any ideas on how to solve this? Let me know if I should provide more information.

Thank you!

EDIT: @dbc requested more exception details.

Newtonsoft.Json.JsonSerializationException was unhandled by user code
  HResult=-2146233088
  Message=Error converting value "{
  "id": 8,
  "användarnamn": "test123",
  "utgång": "2017-03-19T21:15:27.3951877Z"
}" to type 'System.Collections.Generic.Dictionary`2[System.String,System.Object]'. Path '', line 1, position 110.
  Source=Newtonsoft.Json
  StackTrace:
       vid Newtonsoft.Json.Serialization.JsonSerializerInternalReader.EnsureType(JsonReader reader, Object value, CultureInfo culture, JsonContract contract, Type targetType)
       vid Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
       vid Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize(JsonReader reader, Type objectType, Boolean checkAdditionalContent)
       vid Newtonsoft.Json.JsonSerializer.DeserializeInternal(JsonReader reader, Type objectType)
       vid Newtonsoft.Json.JsonSerializer.Deserialize(JsonReader reader, Type objectType)
       vid Newtonsoft.Json.JsonConvert.DeserializeObject(String value, Type type, JsonSerializerSettings settings)
       vid Newtonsoft.Json.JsonConvert.DeserializeObject[T](String value, JsonSerializerSettings settings)
       vid Newtonsoft.Json.JsonConvert.DeserializeObject[T](String value)
       vid JWT.DefaultJsonSerializer.Deserialize[T](String json)
       vid JWT.JsonWebToken.Decode(String token, Byte[] key, Boolean verify)
       vid JWT.JsonWebToken.Decode(String token, String key, Boolean verify)
       vid Webbchat.Controllers.HomeController.LäsJwt(String jwt) i c:\Users\Gustaf\Documents\Visual Studio 2013\Projects\Webbchat\Webbchat\Controllers\HomeController.cs:rad 66
       vid Webbchat.Controllers.HomeController.HämtaMeddelanden(String token, Int32 sistaId) i c:\Users\Gustaf\Documents\Visual Studio 2013\Projects\Webbchat\Webbchat\Controllers\HomeController.cs:rad 169
       vid lambda_method(Closure , ControllerBase , Object[] )
       vid System.Web.Mvc.ActionMethodDispatcher.Execute(ControllerBase controller, Object[] parameters)
       vid System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext, IDictionary`2 parameters)
       vid System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary`2 parameters)
       vid System.Web.Mvc.Async.AsyncControllerActionInvoker.ActionInvocation.InvokeSynchronousActionMethod()
       vid System.Web.Mvc.Async.AsyncControllerActionInvoker.<BeginInvokeSynchronousActionMethod>b__39(IAsyncResult asyncResult, ActionInvocation innerInvokeState)
       vid System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResult`2.CallEndDelegate(IAsyncResult asyncResult)
       vid System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResultBase`1.End()
       vid System.Web.Mvc.Async.AsyncResultWrapper.End[TResult](IAsyncResult asyncResult, Object tag)
       vid System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeActionMethod(IAsyncResult asyncResult)
       vid System.Web.Mvc.Async.AsyncControllerActionInvoker.AsyncInvocationWithFilters.<InvokeActionMethodFilterAsynchronouslyRecursive>b__3d()
       vid System.Web.Mvc.Async.AsyncControllerActionInvoker.AsyncInvocationWithFilters.<>c__DisplayClass46.<InvokeActionMethodFilterAsynchronouslyRecursive>b__3f()
  InnerException: System.ArgumentException
       HResult=-2147024809
       Message=Could not cast or convert from System.String to System.Collections.Generic.Dictionary`2[System.String,System.Object].
       Source=Newtonsoft.Json
       StackTrace:
            vid Newtonsoft.Json.Utilities.ConvertUtils.EnsureTypeAssignable(Object value, Type initialType, Type targetType)
            vid Newtonsoft.Json.Utilities.ConvertUtils.ConvertOrCast(Object initialValue, CultureInfo culture, Type targetType)
            vid Newtonsoft.Json.Serialization.JsonSerializerInternalReader.EnsureType(JsonReader reader, Object value, CultureInfo culture, JsonContract contract, Type targetType)
       InnerException: 

I am using JSON Web Token (JWT) Portable Implementation for .NET 4.5+ for JSON web token generation and encoding.

dbc
  • 104,963
  • 20
  • 228
  • 340
Ag Bengip
  • 11
  • 1
  • 5
  • what are you trying to do? – CodingYoshi Mar 12 '17 at 20:02
  • I'm trying to fetch some user information from a JWT. – Ag Bengip Mar 12 '17 at 20:10
  • Can you paste the full payload you are sending – MindingData Mar 12 '17 at 20:15
  • OK, so the exception is *not* being thrown by `JObject.Parse()`. It's being thrown by `JWT.JsonWebToken.Decode()` which is, internally, also using Json.NET. Is there any chance your JSON string was escaped into a single string containing embedded JSON? That could account for the error. – dbc Mar 13 '17 at 05:04
  • @dbc Oh, that's interesting. These are the only two methods in my application that operate on the JSON - outside of these, it's passed around either as a JWT or as an unserialized/deserialized object - so I think what you're describing would have to occur within the code I've provided, and as far as I can tell these operations are supposed to be essentially symmetrical. – Ag Bengip Mar 13 '17 at 11:08
  • @AgBengip - what is the library you are using to encode and decode tokens? Is it [this](https://github.com/jwt-dotnet/jwt/blob/master/src/JWT/JsonWebToken.cs)? – dbc Mar 13 '17 at 16:33
  • @dbc It's [this one](https://github.com/senzacionale/jwt-portable-dotnet). I did manage to solve my problem, see my answer below. Thanks for your help! – Ag Bengip Mar 13 '17 at 16:51

3 Answers3

1

I thought about how it would be prudent for JWT encoding/decoding methods in C# to accept/return dictionaries, since JSON isn't native to .NET. Sure enough, turns out JWT.JsonWebToken.Encode() doesn't expect a JSON string at all, but an object representing the payload. Therefore the JWT came out malformed, causing the JWT.JsonWebToken.Decode() method to throw a JsonSerializationException. I'll need to pay closer attention when reading the documentation in the future.

public static string CreateJwt(TokenObject input) {
    string key = "This key is fake";
    string jwt = JsonWebToken.Encode(input, key, JwtHashAlgorithm.HS256);
    return jwt;
}

public static TokenObject ReadJwt(string jwt) {
    string key = "This key is fake";
    TokenObject output = JsonWebToken.DecodeToObject(jwt, key) as TokenObject;
    return output;
}
Ag Bengip
  • 11
  • 1
  • 5
0

This is your JSON:

{
   "id": 8,

   "användarnamn": "test123",

   "utgång": "2017-03-19T19:28:00.5493447Z"
}

Create a C# class for that using my answer here. It will produce a class like this:

public class Rootobject
{
  public int id { get; set; }
  public string användarnamn { get; set; }
  public DateTime utgång { get; set; }
}

And here is how to deserialize it:

Rootobject deserialized = 
    JsonConvert.DeserializeObject<Rootobject>("Your JSON");

Here is how to serialize it:

var ro = new Rootobject();
// set properties here
var serialized = JsonConvert.SerializeObject(ro);

By the way you need the NewtonSoft NuGet package if you want to use my answer.

Community
  • 1
  • 1
CodingYoshi
  • 25,467
  • 4
  • 62
  • 64
  • 1
    Thank you, but I'm still getting a `JsonSerializationException` when trying to deserialize. – Ag Bengip Mar 12 '17 at 20:45
  • Is your json in the format I have in my answer or a different format? And what error are you getting? – CodingYoshi Mar 12 '17 at 20:47
  • It's identical to the JSON in your answer, since I added the `Formatting.Indented` argument to the `JsonConvert.SerializeObject()` call. The error is the same as in my original post. – Ag Bengip Mar 12 '17 at 21:00
0

I copied your json string into a text file and successfully deserialized it as follows:

string json = File.ReadAllText(@"C:\MyStuff\json.txt", Encoding.GetEncoding("iso-8859-1"));
var test = JsonConvert.DeserializeObject<Rootobject>(json);

Note that the Rootobject is generated by copying the json string and pasting it using Edit > Paste Special > Paster JSON as Classes in visual studio.

Mahdi
  • 3,199
  • 2
  • 25
  • 35