Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Serializer misconverts "null" string to null value, "true" string to true value #387

Closed
justinyoo opened this issue Feb 27, 2019 · 7 comments

Comments

@justinyoo
Copy link
Contributor

justinyoo commented Feb 27, 2019

Hi, Team.

I'm using YamlDotNet v5.4.0, which is the latest version at the time of this writing. I have a very simple JSON payload like:

{
  "hello": "null",
  "world": "true"
}

As you can see, both "null" and "true" are string, not literally null or true value. Therefore, if I converted that JSON into YAML, the YAML file should look like:

hello: "null"
world: "true"

However, unlike the expectation, it actually returns:

  hello: null,
  world: true

How can I prevent those values from being converted, but left as string literal? I used the code like:

public static string ToYaml(this string json)
{
    if (string.IsNullOrWhiteSpace(json))
    {
        return null;
    }

    var converter = new ExpandoObjectConverter();
    ExpandoObject deserialised;

    try
    {
        deserialised = JsonConvert.DeserializeObject<ExpandoObject>(json, converter);
    }
    catch (Exception ex)
    {
        throw new InvalidJsonException(ex.Message);
    }

    var yaml = new SerializerBuilder().Build().Serialize(deserialised);
}

Obviously the last line var yaml = new SerializerBuilder().Build().Serialize(deserialised); doesn't return the correct value.

Is there a workaround to prevent this?

@justinyoo
Copy link
Contributor Author

The original issue was raised here: TeamYARM/YARM-CLI#1

@justinyoo
Copy link
Contributor Author

I think YAML allows string value with/without the double quotation marks. If YamlDotNet forces to use double quotes for the string values, it could resolve this issue.

@aaubry
Copy link
Owner

aaubry commented Mar 7, 2019

It seems that this behavior could be improved, but I'll need some more time to look into it.

@erndob
Copy link

erndob commented Apr 26, 2019

It seems that this behavior could be improved, but I'll need some more time to look into it.

@aaubry
Are you actively working on it? If you could provide some initial guidance where to start looking, I can try to work on this myself.

@aaubry
Copy link
Owner

aaubry commented Jun 10, 2019

I'm not currently working on this, but I'm not sure either where to start implementing this, sorry.

@kellypleahy
Copy link

I've been looking at this a bit to try to come up with a reasonable solution, as I've had this same issue in my usage of YamlDotNet and am using it for data that I don't have control over so I really either (a) need it to work, or (b) use a different serialization library / format.

I definitely prefer (a) of those two options..., so I thought I'd see if I could provide a patch.

Here's my line of thinking on this:

  1. this problem seems a bit bigger than just null, true, false.
  2. basically, the problem is that some values that are provided as strings in the object being serialized, get turned into another type (or what could be interpreted as another type) on serialization and then get deserialized as a different type (not string).

Here are some examples (all things on the left are meant to be "strings" in type, but the LHS means what they 'look like'):

  1. Null, NULL, null -> null value
  2. true, false, yes, no, True, False, Yes, No -> bool value
  3. integers, floating point numbers -> int/float value

In these cases, doing something with a round trip via expandoObject (or in my case, just serializing to YAML and deserializing even causes problems with Null specifically) will produce incorrect types on the way "back in".

I was thinking about the following:

  1. should YAML emission turn "string" values into something other than strings? I don't think so, but this could have far-reaching impact.
  2. examples might be NULL (obvious one), but what about if someone has a string that has 1E10 (maybe an address or room code or something, for example). On serialization, one might expect that gets turned into a bare value and on deserialization it wouldn't surprise me if this turns into the integer 10 (or floating point value 10.0).
  3. It seems like a good rule (and maybe this is an "option" for the emitter, since it's really a serialization problem, not a deserialization problem) to turn all values that are strings into quoted strings if their value can be misinterpreted as a different "default type" on deserialization to an expando object (or representation graph).

Ex: if you have an expando object that has (string)1E10 in it, and you write that to YAML, it would be '1E10' instead of the "bare" 1E10 (if you have this flag set on the emitter options / serializer options).

Thoughts? I'm happy to put in some time on making this work if someone discuss a couple build issues I'm having trying to get the build to work (it seems to be having problems building some of the other stuff on my machine, and some of the spec tests failed on the latest spec download from yaml-test-suite).

@EdwardCooke
Copy link
Collaborator

This will be fixed when the next release goes out.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants