certik / yaml-cpp

Automatically exported from code.google.com/p/yaml-cpp
MIT License
0 stars 0 forks source link

Type ambguity between strings and numbers #261

Open GoogleCodeExporter opened 9 years ago

GoogleCodeExporter commented 9 years ago
What steps will reproduce the problem?
1.  Parse this YAML string: data: "1"
2.  Try to convert the data like so: node.as<int>(), succeeds (!)
3.  Try to convert the data like so: node.as<string>(), succeeds
4.  See node.Scalar() return the string: 1 

What is the expected output? What do you see instead?

I expect this to work like YAML does in Python where the type of the value the 
user placed in the file is preserved:

>>> import yaml
>>> yaml.load('data: 1')
{'data': 1}
>>> yaml.load('data: "1"')
{'data': '1'}

yaml-cpp totally throws away the true type of the value and it appears 
impossible to figure out what it was in the first place.

What version of the product are you using? On what operating system?

I am using Version 0.5.1-1 on Ubuntu 12.04 32 bits

Please provide any additional information below.

For my use case I can't use YAML cpp because of the ambiguity.

Original issue reported on code.google.com by jli...@gmail.com on 23 Oct 2014 at 7:33

GoogleCodeExporter commented 9 years ago
So you'd like node.as<int>() to throw an exception? I've thought about this 
too, but I'm not sure how I feel about it.

Original comment by jbe...@gmail.com on 25 Oct 2014 at 4:44

GoogleCodeExporter commented 9 years ago
I am not sure exactly.  For my application I switched to jsoncpp which instead 
of having a generic scalar type, has explicit types for uint, int, bool, and 
string.  This preserves all the type information in the parsed file so I can 
handle it properly on my end.

Essentially yaml-cpp is preforming some type erasure which is not what I want 
for my application where I want to be relative strict about the types.

Original comment by jli...@gmail.com on 26 Oct 2014 at 2:03

GoogleCodeExporter commented 9 years ago
jsoncpp is also performing type erasure. You can't write a library that parses 
this stuff without representing each node internally as, well, a node. In 
yaml-cpp, we *can* attempt to understand the type.

Looking at jsoncpp's source, it appears that they throw an exception if you 
access an incorrect type, which we can do, but as I said, I'm not sure if I 
want to. What they *also* do is give you an enum, which we *can't* do, since in 
yaml-cpp, you can parse arbitrary (user-defined) types.

Original comment by jbe...@gmail.com on 26 Oct 2014 at 2:23

GoogleCodeExporter commented 9 years ago
Could you have something like:

enum {
  Map,
  Sequence,
  Int,         // Maybe ScalarInt
  Bool,        // Maybe ScalarBool
  String,      // Maybe ScalarString
  Real,        // Maybe ScalarReal
  UserDefined, // Maybe Unknown?, ScalarUser?
}

In my exact use case I was feeding data from a yaml-cpp into a generic 
boost::any based config store.  With the cast and catch exceptions approach I 
was treating "1000" and 1000 as an integer when the end user really wanted 
their string back. 

Original comment by jli...@gmail.com on 26 Oct 2014 at 2:37

GoogleCodeExporter commented 9 years ago
No, I don't think I'll extend enum to specific scalar types, because I like 
that various user types are first-class.

I'll leave this issue open and think about whether the cast should throw an 
exception.

Original comment by jbe...@gmail.com on 26 Oct 2014 at 11:36