-1

This is my sample dictionary:

{ 
  "gross_price" = "6.5678565676";
  "gross_price_total" = "6.00";
}    

Now I parse that values:

if let grossPriceTotal = dictionary["gross_price_total"] as? Double {
    order!.grossPriceTotal = grossPriceTotal
    //doesn't work
}

if let grossPriceTotal = dictionary["gross_price"] as? Double {
    order!.grossPriceTotal = grossPriceTotal
    //works
}

Why the first conditional is not converted, and the second one is?

This is real screen from the app: enter image description here

I would like to understand why in this case it was, indeed, converted to Double easily, since it looks like a String, and it shouldn't be converted?

Bartłomiej Semańczyk
  • 59,234
  • 49
  • 233
  • 358
  • 2
    What about the answers you got in your previous [question](http://stackoverflow.com/questions/29919805/cannot-convert-string-to-double-in-swift)? You're still using the same code despite having received valuable solutions... – Eric Aya Apr 28 '15 at 13:30
  • I know that I am able to do this with `("67.78" as NSString).doubleValue` but it is not the point. I would like to know, why once (when I have more digits than 2) it is converted to `Double`, and once (when I have 2 digits) it is not – Bartłomiej Semańczyk Apr 28 '15 at 13:32
  • `"6.5678565676"` is a string as well, and *not* converted with `as? Double`. Can you show a self-contained reproducible example? – Martin R Apr 28 '15 at 13:34
  • you're trying to downcast a String into Double, which will always fail. I put your code in a playground, and didn't compile. "Cast from 'String' to unrelated type 'Double' always fails" – Ramy Kfoury Apr 28 '15 at 13:41
  • @Martin R, I added example with image. If you were right, it should not stop at that line... So why it stopped? On console there is printed response from server.. – Bartłomiej Semańczyk Apr 28 '15 at 13:43
  • Suggestion: Add a `println()` inside the if-block to make sure that it is *really* executed. – Martin R Apr 28 '15 at 13:46
  • @Martin R I updated the image. I only try to understand why it is like that... – Bartłomiej Semańczyk Apr 28 '15 at 13:50
  • A println() for one of the strings you claim is converted might be more useful than "a2"... like print the value for `historicTotal` for example. Or type `po historicOrdersCount` in the debugger if Xcode is paused on line 67. – Eric Aya Apr 28 '15 at 13:55
  • @ericd I updated an image – Bartłomiej Semańczyk Apr 28 '15 at 14:02
  • Ok. Let's try something different. When Xcode is paused, do ALT+CLICK on your variables. Xcode will show you the *type* of the variables. What are the types? Are they what you expect? – Eric Aya Apr 28 '15 at 14:07
  • Of course this is what I expect, when I cast to Double, and if I am inside the conditionals scope, there must be a double, otherwise it wouldn't get inside the scope – Bartłomiej Semańczyk Apr 28 '15 at 15:10

1 Answers1

3

Short answer:

  • dictionary["gross_price_total"] is a string, and therefore as? Double fails.
  • dictionary["gross_price"] is a number, therefore as? Double succeeds. However, println(dictionary) prints this number as "6.5678565676", so that it looks like a string.

Long answer:

Here is a complete example demonstrating the problem:

let jsonString = "{ \"gross_price\" : 5.23, \"gross_price_total\" : \"6.00\" }"
println("JSON: \(jsonString)")

let jsonData = jsonString.dataUsingEncoding(NSUTF8StringEncoding)!
var error : NSError?
if let dictionary : AnyObject = NSJSONSerialization.JSONObjectWithData(jsonData, options: nil, error: &error) {
    println("dictionary: \(dictionary)")

    if let grossPriceTotal = dictionary["gross_price_total"] as? Double {
        println(grossPriceTotal)
    } else {
        println("no grossPriceTotal")
    }

    if let grossPriceTotal = dictionary["gross_price"] as? Double {
        println(grossPriceTotal)
    } else {
        println("no gross_price")
    }
} else {
    println(error)
}

Output:

JSON: { "gross_price" : 5.23, "gross_price_total" : "6.00" }

dictionary: {
    "gross_price" = "5.23";
    "gross_price_total" = "6.00";
}

no grossPriceTotal
5.23

The value of "gross_price" is a number, but printing the dictionary shows it as a string. This number can be converted with as? Double.

The value of "gross_price_total" is a string, and it can not be converted with as? Double.

So the confusion comes only from the fact that println(dictionary) encloses numbers with fractional digits in quotation marks, so that they cannot be distinguished from strings.

The description format for NSArray and NDDictionary is described in Old-Style ASCII Property Lists (emphasis added):

A string is enclosed in double quotation marks, for example:
"This is a string"
The quotation marks can be omitted if the string is composed strictly of alphanumeric characters and contains no white space (numbers are handled as strings in property lists).

Martin R
  • 529,903
  • 94
  • 1,240
  • 1,382
  • So, the conclusion is: 1. If I **cannot** convert directly to `Double` it **must be** a `String`. If I **can** convert to `Double` it means that it **must be** a `number` even if I see the `String`, right? 2. The number of digits doesn't matter here, right? 3. If I cannot convert to Double it means, that I got from server `String` instead of `number`, right? Can you confirm my understanding, please? I will be very grateful. – Bartłomiej Semańczyk Apr 28 '15 at 15:22
  • How can I improve my question to make it not repeated? Because I was looking for the answer, but I haven't found. Now you understand what I mean... Thanks for your help @Martin R. – Bartłomiej Semańczyk Apr 28 '15 at 15:25
  • 1
    @BartłomiejSemańczyk: You have to check all possible types. Check for Double first, and if that fails check for String. If that fails, set some default value or report an error or whatever. – I think some people downvoted your question because it *seemed* that you try (again) to convert a string to a double, and that's what I *initially* thought as well. Later it turned out to be an interesting problem (and I gave you +1). Perhaps all that information that you added later should have been there in the first place. – Martin R Apr 28 '15 at 18:01
  • @BartłomiejSemańczyk: I cannot see that your question has been marked as a duplicate. Perhaps someone "flagged" it, but there is no closing vote. – Martin R Apr 28 '15 at 21:11
  • "This question may already have an answer here...". - is not that? – Bartłomiej Semańczyk Apr 28 '15 at 21:13
  • @BartłomiejSemańczyk: I cannot see that. I *assume* that someone (with <3000 rep) "flagged" the question as a duplicate, but unless other people with higher rep actually vote to "close" this has no consequences. – Martin R Apr 28 '15 at 21:26
  • ok thanks, I think I remove my previous question, because I do not like to repeat questions before searching answer before... – Bartłomiej Semańczyk Apr 28 '15 at 21:28