-1

I am trying to load the following yaml:

yaml_string = """
key:
- [HELLO]
- another string
- another
"""
yaml.safe_load(yaml_string) # returns {"key": [["HELLLO"], "another_string", "another"}

and the result is a list containing the HELLO string. I wan to load this a string value that is

type(yaml.save_load(yaml_string).get("key")[0])
<class 'str'>

Since yaml describes some sort of commnads that are formatted this way, it is necessary to be read as strings and not as sequences. Basically I want to be able to read strings that start and end with brackets. As explained to the comment underneath, unfortunatelly it is not possible to add " since the yaml files were created by a Java app using Jackson which didn't have a problem turning yaml into an object and treating entries that start and end with brackets as strings. The files are to many for users to start adding quotes.

Is this possible?

EDIT: Added a more complete example

Apostolos
  • 7,763
  • 17
  • 80
  • 150
  • if you want a string then why are you using `-` and `[ .. ]`? these make the value a list of lists – DeepSpace Feb 17 '20 at 15:16
  • I edited my question. In the yaml it is a key of list of items. And I want them all strings – Apostolos Feb 17 '20 at 15:21
  • 1
    You still didn't explain why you added the `[...]` around `HELLO`. – mkrieger1 Feb 17 '20 at 15:24
  • So, to be clear, instead of `{"key": [["HELLLO"], "another_string", "another"}` you want `{"key": ["[HELLLO]", "another_string", "another"}`? – DeepSpace Feb 17 '20 at 15:25
  • It is not possible to read those items just as strings (in a general way). `[...]` are part of the official YAML syntax (like in JSON). It is called flow style (opposed to the default block style). You would have to implement a parser which ignores flow style syntax. Basically, if you expect `[foo]` to be a string `"[foo]"`, what you have is not YAML. – tinita Feb 18 '20 at 10:40

3 Answers3

1

surround [HELLO] with quotes:

import yaml

yaml_string = """
key:
- "[HELLO]"
- another string
- another
"""

print(yaml.safe_load(yaml_string))

outputs

{'key': ['[HELLO]', 'another string', 'another']}
DeepSpace
  • 78,697
  • 11
  • 109
  • 154
  • Yes this is not possible, due to the fact that most of my yaml files were created automatically, from not containing quotes, and there too many to do it. Is there a way pyyaml does this by default. In general I want pyyaml to skip converting to lists booleans etc. I want them plain strings. I want to handle casting in a different step – Apostolos Feb 17 '20 at 15:30
  • @Apo you can use regex replace, no? – OneCricketeer Feb 18 '20 at 11:19
  • @cricket_007 that could be pretty fragile, because there could be other locations with a `[` character – tinita Feb 18 '20 at 11:29
  • @tinita So? You could match against `-\s+\[[^]+\]` – OneCricketeer Feb 18 '20 at 14:12
  • @cricket_007 sure, it might work, if the "strings" in question are always a sequence item and `- [...]` does not appear anywhere else. I don't know how the full YAML files look like. both regex replace and my solution have advantages and disadvantages – tinita Feb 18 '20 at 14:27
0

If you want the string "HELLO" as a result, then remove the [...] around it in the YAML:

yaml_string = """
key:
- HELLO
"""
print(yaml.safe_load(yaml_string))
# {'key': ['HELLO']}

If you want the string "[HELLO]" (instead of a list containing the string "HELLO"), then add quotes in the YAML:

yaml_string = """
key:
- "[HELLO]"
"""
print(yaml.safe_load(yaml_string))
# {'key': ['[HELLO]']}
OneCricketeer
  • 179,855
  • 19
  • 132
  • 245
mkrieger1
  • 19,194
  • 5
  • 54
  • 65
0

The [] syntax is part of the YAML syntax. If you created this with a program and those are supposed to be strings, the program you used did not implement YAML correctly, as the strings would have to be quoted.

You can try out the following experimental perl script to add quotes around [...]. This relies on the assumption that your documents do not use flow style sequences that should be real sequences. Also it might not work for all cases.

It will definitely not work if the string only has an opening [ but not a closing one.

#!/usr/bin/env perl
use strict;
use warnings;
use 5.010;

use YAML::LibYAML::API::XS;

my $yaml = <<'EOM';
key:
- [HELLO]
- another string
- another
- [HELLO2]
EOM

my @lines = split /(?<=\n)/, $yaml;

my @events;
YAML::LibYAML::API::XS::parse_string_events($yaml, \@events);
while (my $event = shift @events) {
    if ($event->{name} eq 'sequence_start_event' and $event->{style} == 2) {
        my $start = $event->{start};
        my $line = $start->{line};
        my $column = $start->{column};
        # Add single quote before [
        substr($lines[ $line ], $column, 0) = "'";
        # find the next matching `]`
        while (my $event = shift @events) {
            if ($event->{name} eq 'sequence_end_event') {
                my $end = $event->{end};
                my $line = $end->{line};
                # Add single quote after ]
                # add 1 because we modified the line already and added one char
                my $column = $end->{column} + 1;
                substr($lines[ $line ], $column, 0) = "'";
                last;
            }
        }
    }
}

$yaml = join '', @lines;
say $yaml;

You might be able to do the same with Python if you have an interface to the libyaml API.

Output:

key:
- '[HELLO]'
- another string
- another
- '[HELLO2]'
mkrieger1
  • 19,194
  • 5
  • 54
  • 65
tinita
  • 3,987
  • 1
  • 21
  • 23