1

I am trying to get the value from Dictionary(JSON deserialized) and parse it as long.

When I quick viewed the variable I found there is no "M" as part of the out parameter a s given below enter image description here

But when I click into the value, I found "M" being added to the value as given

enter image description here

The problem here is the long.Parse fails when there is "M". If I remove "M" manually long.Parse works fine.

Why this strange behavior? and how to avoid this?

Edit:

Value in payloadJson is

{
  "http://schemas.microsoft.com/ws/2008/06/identity/claims/userdata": "admin@admin.com",
  "expiry": 1551354842.0,
  "issuedAt": 1551351242.0,
  "notBefore": 1566989642.0,
  "isRefresh": false
}

var payloadData = jsonSerializer.Deserialize<Dictionary<string, object>>(payloadJson);

object exp;
if (payloadData != null && (checkExpiration && payloadData.TryGetValue("expiry", out exp)))
{
    var validTo = FromUnixTime(long.Parse(exp.ToString()));
}

Console app

using JWT;
using JWT.Serializers;
using System.Collections.Generic;
using System.Web.Script.Serialization;

namespace TestApp
{
    class Program
    {
        static void Main(string[] args)
        {
            var token = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJodHRwOi8vc2NoZW1hcy5taWNyb3NvZnQuY29tL3dzLzIwMDgvMDYvaWRlbnRpdHkvY2xhaW1zL3VzZXJkYXRhIjoiYWRtaW5AYWRtaW4uY29tIiwiZXhwaXJ5IjoxNTUxMzU0ODQyLjAsImlzc3VlZEF0IjoxNTUxMzUxMjQyLjAsIm5vdEJlZm9yZSI6MTU2Njk4OTY0Mi4wLCJpc1JlZnJlc2giOmZhbHNlfQ.E-fR8VAFAy-mosEfQC3ZPlN2kZBQg02FLYuChdhqHNhzgVsbIjMXUFLHYowf0aUwQRcyoFR2mpiD_5I6drGdnQ";
            var jsonSerializer = new JavaScriptSerializer();
            IJsonSerializer serializer = new JsonNetSerializer();
            IDateTimeProvider provider = new UtcDateTimeProvider();
            IJwtValidator validator = new JwtValidator(serializer, provider);
            IBase64UrlEncoder urlEncoder = new JwtBase64UrlEncoder();
            IJwtDecoder decoder = new JwtDecoder(serializer, validator, urlEncoder);
            var payloadJson = decoder.Decode(token, "GAFaS9W4Ys2AA2VHadPdje9gaeWjY8", true);
            var payloadData = jsonSerializer.Deserialize<Dictionary<string, object>>(payloadJson);

            object exp;
            payloadData.TryGetValue("expiry", out exp);
            var tempExpiry = long.Parse(exp.ToString());
        }
    }
}
Gopi
  • 5,656
  • 22
  • 80
  • 146
  • What do you mean by "click into the value"? Your screenshots look identical, other than the addition of the "M" suffix. – canton7 Feb 28 '19 at 11:17
  • can you show us sample data of your dict? (no pun intended) – jomsk1e Feb 28 '19 at 11:17
  • What *type* does the object that you get back have? – Lasse V. Karlsen Feb 28 '19 at 11:18
  • I suspect what you've got is a boxed `double` or `decimal`. In this case, `Convert.ToInt64(obj)` will be better than turning it into a string, and then parsing it as a long. – canton7 Feb 28 '19 at 11:18
  • @canton7 if you try to modify the value during run time, you will click on the value correct? – Gopi Feb 28 '19 at 11:18
  • So what happens if you don't "click into the value", does it work then? – Lasse V. Karlsen Feb 28 '19 at 11:19
  • @Gopi OK, so the act of modifying it in the debugger caused it to gain the "M" suffix? – canton7 Feb 28 '19 at 11:19
  • @LasseVågsætherKarlsen, long.Parse throws input string was not in correct format. I should remove "M" manually after clicking – Gopi Feb 28 '19 at 11:20
  • 1
    I strongly suspect it's a boxed decimal, which explains the `M` suffix. It would help if you could remove the debugger from the equation though, and provide a [mcve]. – Jon Skeet Feb 28 '19 at 11:20
  • 1
    The problem here now is that your question isn't clear as to what the problem is. If it runs fine, at runtime, if you just leave the program be, then this is valuable knowledge. If the problem with the M comes if you use the debugger to change the value, then this too is valuable information. We need to know if the M comes as part of your program/code, or because of the debugger doing something. Can you please clarify what happens if you don't debug the program and don't try to modify the value? – Lasse V. Karlsen Feb 28 '19 at 11:21
  • @JonSkeet Updated the question with actual code and value – Gopi Feb 28 '19 at 11:24
  • @LasseVågsætherKarlsen it doesn't run fine during runtime. :( – Gopi Feb 28 '19 at 11:26
  • So is there a problem when you're not debugging, or not? (This still isn't a [mcve].) – Jon Skeet Feb 28 '19 at 11:26
  • @JonSkeet The problem is during runtime, the long.Parse throws input string was not in correct format error. So I debugged to find what is the actual value. When I hovered over the exp value, it was displaying the correct value (image1) but further debugging resulted in same error. So I tried to modify the value by clicking in to the exp variable and found "M" got append and if I remove the M from exp object, long.Parse works as expected. – Gopi Feb 28 '19 at 11:29
  • Since we don't have all the details, such as @JonSkeet mentioning a [mcve], it is hard for us to verify what the problem is. I saved your json to a file and copied and hacked together your code, and it works just fine, so there has to be something more here. If it doesn't run fine at runtime, can you please post the exception and stack trace? – Lasse V. Karlsen Feb 28 '19 at 11:29
  • @JonSkeet When I used Convert.ToInt64 as per one of the answer, it works as expected. But if you can help me understand why it will be helpful – Gopi Feb 28 '19 at 11:33
  • Details we are missing are things like which json library you're using (I ask because my copy of json.net doesn't have this particular Deserialize method other than using a JsonReader and your variable names doesn't seem to indicate that you're using a reader), but even when I fixed that the `exp` variable came back as `Int64`, which wouldn't have `.0` when shown using the debugger (I verified this), so again, there are some parts missing here. – Lasse V. Karlsen Feb 28 '19 at 11:33
  • Try this: `Debug.WriteLine(exp.GetType().FullName); Debug.WriteLine(exp.ToString());`, and tell us what it outputs, before you try to parse the value. You can use `Console.WriteLine` instead if this makes it easier to capture the output. – Lasse V. Karlsen Feb 28 '19 at 11:36
  • 1
    "But if you can help me understand why it will be helpful" - sure, as soon as we have a [mcve] that fails without the debugger getting involved. Note that to be **complete**, I'm looking for a short console app I can copy/paste/compile/run with no other changes. – Jon Skeet Feb 28 '19 at 11:38
  • @LasseVågsætherKarlsen this is the result System.Decimal, 1551354842.0 and I am using System.Web.Script.Serialization to Deserialize – Gopi Feb 28 '19 at 12:07
  • @JonSkeet I've updated the question with a console app. I also found that when I remove "M" manually, the value "xxx.0M" changes to "xxx" which means it removes ".0" as well – Gopi Feb 28 '19 at 12:18
  • 1
    Now it's not minimal - we don't need the JWT package to demonstrate it, for example. Here's a more reasonable [mcve]: https://gist.github.com/jskeet/0edb911cfd98ce22ae7d3b905a18b25b Note that the value in `payloadJson` is *not* what you show it to be in the question - it's 1551354842.0, including the ".0" part. That's important. – Jon Skeet Feb 28 '19 at 13:30
  • So I've confirmed that Json.Net (which is not the library in use here, I know) will deserialize `"expiry":1551354842` as an `Int64`, and the JavascriptSerializer will deserialize it as `Int32` (I tested this), the question is, are you sure your json is the way you said it was? – Lasse V. Karlsen Feb 28 '19 at 13:38
  • @JonSkeet It was my mistake. I tried to format the JSON using https://jsoneditoronline.org/ and it removed the ".0" part from the value. – Gopi Mar 01 '19 at 06:22
  • @LasseVågsætherKarlsen No, the JSON is different. It was my mistake. I tried to format the JSON using jsoneditoronline.org and it removed the ".0" part from the value – Gopi Mar 01 '19 at 06:23

1 Answers1

3

M means decimal, D means double, if you want to parse to long, this will work:

long vOut = Convert.ToInt64(exp);

This is the signature of TryGetValue:

public bool TryGetValue(TKey key, out TValue value) {
    int i = FindEntry(key);
    if (i >= 0) {
        value = entries[i].value;
        return true;
    }
    value = default(TValue);
    return false;
}

You should read more about boxing and unboxing.

You have a variable exp of type object. You have a decimal and you want to put it into exp. You can make a new object that can store the decimal and then you assign a reference to that object to exp. That is boxing.

Just an example:

bool x = false; //stack
object o = b; //box
bool x2 = (bool)o; //unboxing

why we use boxing? mostly to check nulls:

if (x == null) //will not compile because bools cannot be of null
if (o == null) //will compile and always returns false

I hope this helps.

jomsk1e
  • 3,585
  • 7
  • 34
  • 59