1

I am trying to extract currency value from Json using Newtonsoft json library. The SelectToken method gives me data as object. I am converting it to string and inserting in DB. When the value is say 9.9 I get exact value as string but when there is 9.0 then ToString() truncates decimal values and returns me only 9. I did lot of research but did not find any answer.

I am expecting below values as string from object. I don't want additional decimal places or remove all. I need it as it is.

Object => expected string

9 => 9

9.0 => 9.0

9.00 => 9.00

9.9 => 9.9

9.99 => 9.99

Edit:

Simple question. If object a has value 9.0 then I want same value 9.0 as string.

similarly if it has 9 then I want string 9

if it has 9.90 then I want 9.90 as string

if it has 9.99 then I want 9.99 as string

I hope I am clear this time.

Sandeep Gupta
  • 127
  • 1
  • 12
  • 1
    Why do you need a string? Is the column type in database of type VARCHAR or any other string type? – Sir Rufo Jun 18 '17 at 00:36
  • in DB it is varchar – Sandeep Gupta Jun 18 '17 at 00:37
  • 1
    You should never do that. Use decimal or numeric or any other numeric type for numeric values – Sir Rufo Jun 18 '17 at 00:39
  • The value `9.0` is identical to the value `9`. Why is it a problem that the trailing decimal and zero are omitted? If you don't want the value to be omitted, why do you convert to a numerical format in the first place (since JSON is strictly text...you could just keep the value as text)? – Peter Duniho Jun 18 '17 at 00:39
  • If I use this code price.SelectToken("ListPrice", false).ToString() then it gives me only 9 only. I understand 9.0 is same as 9 but my client wants it as it it is :( – Sandeep Gupta Jun 18 '17 at 00:46
  • 2
    Do note that behavior also varies depending on whether you are using `decimal` or `double` (the former being more appropriate for currency values). Frankly, your question is unclear, but here are some likely duplicates, depending on what exactly it is you're actually asking: https://stackoverflow.com/q/11037766, https://stackoverflow.com/q/4415596, and https://stackoverflow.com/q/32485064. In any case, there does not seem to be anything novel about your question; you should spend some time searching Stack Overflow for the existing questions that address your problem, as they surely do exist. – Peter Duniho Jun 18 '17 at 00:47
  • What type is it in json? – CodingYoshi Jun 18 '17 at 00:59
  • it is showing as double. I converted to double where it retains the decimal places but as soon as I convert it into string then be becomes 9 only. – Sandeep Gupta Jun 18 '17 at 01:01
  • @Sir Rufo, I know that but the table already has some string value like Free because that column is price column. – Sandeep Gupta Jun 18 '17 at 01:04
  • 1
    Shouldn't "Free" product be having price zero? You are risking a big trouble of maintenance here. Its good if you get the things in line now only. – Chetan Jun 18 '17 at 01:33
  • Was my question wrong or off the topic? Why did I get a downvote? @CodingYoshi exactly answered it. – Sandeep Gupta Jun 19 '17 at 22:20

2 Answers2

2

If you use JObject.Parse, in order to do what you need, your value must be a string. If it's a floating point value, you won't get its decimals. Check out this example:

string json = "{ sValue1: '9.00', sValue2: '9.0000', dValue1: 9.00, dValue2: 9.0000 }";

JToken token = JObject.Parse(json);

// prints 9.00, or 9,00 if comma is your decimal separator
Console.WriteLine((decimal)token.SelectToken("sValue1"));
// prints 9.00 regardless of your decimal separator
Console.WriteLine((string)token.SelectToken("sValue1"));

// prints 9.0000, or 9,0000 if comma is your decimal separator
Console.WriteLine((decimal)token.SelectToken("sValue2"));
// prints 9.0000 regardless of your decimal separator
Console.WriteLine((string)token.SelectToken("sValue2"));

// All these print 9
Console.WriteLine((decimal)token.SelectToken("dValue1"));
Console.WriteLine((string)token.SelectToken("dValue1"));
Console.WriteLine((decimal)token.SelectToken("dValue2"));
Console.WriteLine((string)token.SelectToken("dValue2"));

Casting as double always removes trailing zeros.

Summarizing, these are the options:

  1. String => string: exact outcome
  2. String => decimal: exact outcome if the decimal separator matches
  3. String => float/double: without trailing zeros
  4. Float => whatever: without trailing zeros

Just for the record, decimal data type keeps track of the precision used, so it knows if there are trailing zeros.

If you already have a class for all the properties in the JSON string, you can use JsonConvert.DeserializeObject, which keeps the trailing zeros if you store those in a string even though if they come as float. You can see this in CodingYoshi's answer.

PS: As others mentioned, numeric values should be stored as such in the DB, but that's for another question.

Andrew
  • 7,602
  • 2
  • 34
  • 42
1

In the comment to your question you said:

If I use this code price.SelectToken("ListPrice", false).ToString() then it gives me only 9 only. I understand 9.0 is same as 9 but my client wants it as it it is

In the comments various people suggested to keep it as numeric and that is good advice. However, if your client wants it that way, then that is how it has to be. The easiest solution would be to deserialize it into a string instead of a numeric type. For example imagine you have this JSON:

{
    Unit: 15.0000,
    Value: 14.000
}

If you deserialize it into the following type:

public class ItemSize
{
    public string Unit { get; set; }
    public double Value { get; set; }
}

then Unit, because it is a string, will keep all the decimals but Value will not. So just make your property a string type and JSON.NET will take care of it for you. You can test the above with this code:

var val = JsonConvert
    .DeserializeObject<ItemSize>("{ Unit: 15.0000, Value: 14.000 }");
CodingYoshi
  • 25,467
  • 4
  • 62
  • 64
  • Are you sure? In my tests, all those trailing zeros are lost as soon as the JSON string is parsed. That makes sense, as in JavaScript `9.0` and `9.0000` are stored exactly the same. – Andrew Jun 18 '17 at 02:27
  • @Andrew Look at my class, I made the property `Unit` a `string` type. Is yours a `string` type? Do the test in my answer and you will see it gives the result you want. – CodingYoshi Jun 18 '17 at 02:29
  • I see, with that methods it keeps the decimals, with `JObject.Parse` (the one Sandeep seems to be using) it doesn't. – Andrew Jun 18 '17 at 03:27
  • @CodingYoshi, Awesome! I know it is not the pro way to do it but this is need of the hour so I had to do it. – Sandeep Gupta Jun 19 '17 at 21:39