Total Pageviews

2018/05/12

[snakeyaml] How to get rid of single quote in YAML when value is true / false?

Problem
The expected YAML is:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
  intents:
  - greet
  - inform
  - others
  - question
  entities:
  - userid
  - is_account_locked
  - pass_company_check
  action_masking: true
  action_factory: remote
  actions:
  - utter_default
  - utter_greet
  - confirm:
      dependency:
        slots:
        - userid
  - unlock:
      dependency:
        slots:
        - userid
        - is_account_locked

Here has the original source code:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
  package test.albert.snakeyaml;
  
  import java.util.Arrays;
  import java.util.HashMap;
  import java.util.List;
  import java.util.Map;
  
  import org.yaml.snakeyaml.DumperOptions;
  import org.yaml.snakeyaml.Yaml;
  import org.yaml.snakeyaml.constructor.Constructor;
  import org.yaml.snakeyaml.nodes.Tag;
  import org.yaml.snakeyaml.representer.Representer;
  
  import lombok.AllArgsConstructor;
  import lombok.Data;
  import lombok.extern.slf4j.Slf4j;
  
  @Slf4j
  public class SnakeYamlTest {
  
      public static void main(String[] args) {
          // Set DumperOptions options
          DumperOptions options = new DumperOptions();
          options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
          options.setPrettyFlow(true);
  
          // overwrite Representer
          Representer representer = new Representer();
          representer.addClassTag(ActionAttribute.class, Tag.MAP);
  
          // Create Yaml instance with Representer and DumperOptions
          Yaml yaml = new Yaml(new Constructor(), representer, options);
  
          // Prepare map data for YAML
          Map<String, Object> actionMap1 = new HashMap<>();
          actionMap1.put("confirm", new ActionAttribute(new Dependency(Arrays.asList("userid"))));
  
          Map<String, Object> actionMap2 = new HashMap<>();
          actionMap2.put("unlock", new ActionAttribute(new Dependency(Arrays.asList("userid", "is_account_locked"))));
  
          Map<String, Object> map = new HashMap<>();
          map.put("intents", Arrays.asList("greet", "inform", "others", "question"));
          map.put("entities", Arrays.asList("userid", "is_account_locked", "pass_company_check"));
          map.put("action_factory", "remote");
          map.put("actions", Arrays.asList("utter_default", "utter_greet", actionMap1, actionMap2));
          map.put("action_masking", "true");
  
          // Serialize a Java object into a YAML String
          String output = yaml.dump(map);
          log.info("\n" + output);
      }
  
      @Data
      @AllArgsConstructor
      private static class ActionAttribute {
          Dependency dependency;
      }
  
      @Data
      @AllArgsConstructor
      private static class Dependency {
          private List<String> slots;
      }
  }

But the action_masking value had been added single quote to its front and rear, how to remove single quote?
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
  intents:
  - greet
  - inform
  - others
  - question
  entities:
  - userid
  - is_account_locked
  - pass_company_check
  action_masking: 'true'
  action_factory: remote
  actions:
  - utter_default
  - utter_greet
  - confirm:
      dependency:
        slots:
        - userid
  - unlock:
      dependency:
        slots:
        - userid
        - is_account_locked


How-To
According to snakeyaml source code, these values will regard as boolean value and add single quote from it front and rear



Therefore, you need to create a custom resolver to overwrite its value (remove true/false)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
  package test.albert.snakeyaml;
  
  import org.yaml.snakeyaml.nodes.Tag;
  import org.yaml.snakeyaml.resolver.Resolver;
  
  public class CustomResolver extends Resolver {
      protected void addImplicitResolvers() {
          addImplicitResolver(Tag.BOOL, BOOL, "yYnNoO");
      }
  }

Then create Yaml instance with this custom resolver
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
  package test.albert.snakeyaml;
  
  import java.util.Arrays;
  import java.util.HashMap;
  import java.util.List;
  import java.util.Map;
  
  import org.yaml.snakeyaml.DumperOptions;
  import org.yaml.snakeyaml.Yaml;
  import org.yaml.snakeyaml.constructor.Constructor;
  import org.yaml.snakeyaml.nodes.Tag;
  import org.yaml.snakeyaml.representer.Representer;
  
  import lombok.AllArgsConstructor;
  import lombok.Data;
  import lombok.extern.slf4j.Slf4j;
  
  @Slf4j
  public class SnakeYamlTest {
  
      public static void main(String[] args) {
          // Set DumperOptions options
          DumperOptions options = new DumperOptions();
          options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
          options.setPrettyFlow(true);
  
          // overwrite Representer
          Representer representer = new Representer();
          representer.addClassTag(ActionAttribute.class, Tag.MAP);
  
          // Create Yaml instance with Representer, DumperOptions, CustomResolver
          Yaml yaml = new Yaml(new Constructor(), representer, options, new CustomResolver());
  
          // Prepare map data for YAML
          Map<String, Object> actionMap1 = new HashMap<>();
          actionMap1.put("confirm", new ActionAttribute(new Dependency(Arrays.asList("userid"))));
  
          Map<String, Object> actionMap2 = new HashMap<>();
          actionMap2.put("unlock", new ActionAttribute(new Dependency(Arrays.asList("userid", "is_account_locked"))));
  
          Map<String, Object> map = new HashMap<>();
          map.put("intents", Arrays.asList("greet", "inform", "others", "question"));
          map.put("entities", Arrays.asList("userid", "is_account_locked", "pass_company_check"));
          map.put("action_factory", "remote");
          map.put("actions", Arrays.asList("utter_default", "utter_greet", actionMap1, actionMap2));
          map.put("action_masking", "true");
  
          // Serialize a Java object into a YAML String
          String output = yaml.dump(map);
          log.info("\n" + output);
      }
  
      @Data
      @AllArgsConstructor
      private static class ActionAttribute {
          Dependency dependency;
      }
  
      @Data
      @AllArgsConstructor
      private static class Dependency {
          private List<String> slots;
      }
  }

No comments: