Allow to configure different Scalarstyle for different scalar type

Issue #458 wontfix
green blood created an issue

I try to write spring boot yaml configurations. Unfortunatly Spring boot does not like strings without quotes.

But if i enable SINGLE_QUAOTED Scalar style ints get written as !!int '7' which Spring boot does not like again.

Diving deep into the code i found out i might could manipulate Emitter class.

Please give a way to allow different scalar types, it was requested multiple times already in stackoverflow and also here in issues.

Comments (10)

  1. green blood reporter

    For other people having the same problem

    I found at least a dirty workarround:

    Extending Representer and than overriding representJavaBeanProperty Method.

    Inside this method add this code:

    protected NodeTuple representJavaBeanProperty(
                Object javaBean,
                Property property,
                Object propertyValue,
                Tag customTag) {
            if (Tag.STR.equals(valueNode.getTag())) {
    
                try {
                    Field f1 = valueNode.getClass().getDeclaredField("style");
                    f1.setAccessible(true);
                    f1.set(valueNode, DumperOptions.ScalarStyle.SINGLE_QUOTED);
                } catch (Exception e) {
                    throw new IllegalStateException(e);
                }
            }
              return new NodeTuple(representData(property.getName()), valueNode);
    }
    

  2. Andrey Somov

    I do not get what you achieve with your code.

    Probably, you can do the same simply removing (not adding) the resolvers that you do not need.

    For instance for integers, numbers, time and date.

    You can find examples to manage resolvers in the tests.

  3. Andrey Somov

    I think I understand better what is expected. Indeed now this is not simple.

    We can change line 764 in Emitter to make something like this:

        protected DumperOptions.ScalarStyle chooseScalarStyle(ScalarEvent ev) {
    

    but the chooseScalarStyle() method contains a lot of private variables.

    Any suggestion is welcome !

  4. Andrey Somov

    Another proposal. The API of SnakeYAML is not easy to change. We must maintain the backwards compatibility.

    But we have freedom to change SnakeYAML Engine. There we can change Emitter to implement what you expect.

  5. green blood reporter

    I have a proposal that is backward compatible and will enhance possibilities.

    Add a method to dumperoptions allowing to set a strategy for lookup of scalar type. If the strategy is set it will be used. If not than default will be used like it is at the moment.

    interface ScalarStyleLookUpStrategy{
        DumperOptions.ScalarStyle chooseScalarStyle(ScalarEvent event);
    }
    
    ScalarStyleLookUpStrategy myownLookupStrategy= new ScalarStyleLookUpStrategy() {
    
      @Override
      public DumperOptions.ScalarStyle chooseScalarStyle(ScalarEvent event) 
      {
        if(Tag.STR.equals(event.getTag()))
        {
          return DumperOptions.ScalarStyle.SINGLE_QUOTED;
        }
        return null;
      }
    }
    
    
    dumperOptions.setScalarStyleLookupStrategy(myownLookupStrategy);
    

    What do you think?

  6. Andrey Somov

    Well, I am going to implement a similar thing for the SnakeYAML Engine project.

    For the SnakeYAML itself it is not that easy, because the current implementation of chooseScalarStyle() depends on instance variables (for instance ScalarAnalysis).

    The custom implementation of the ScalarStyleLookUpStrategy interface must also have access to the instance variables.

    Probably we can refactor Emitter to get rid of the instance variables to choose the scalar style. Or all the variables should be passed as arguments. For instance:

    interface ScalarStyleLookUpStrategy{
        DumperOptions.ScalarStyle chooseScalarStyle(ScalarEvent event, ScalarAnalysis analysis);
    }
    

    but it exposes a lot of implementation details.

  7. green blood reporter

    That is true depends on the goal you want to archive, ofcourse regarding the design it would be best if you would have a DefaultLookupStrategy which contains the logic of the original choosescalarstyle method. This would also encapsulate the logic and will make it better testable also the Single Responsibility Principle would say to do so.

    However if this is too much work you could also do it different and give only the result of your analysis in. This means the ScalarType your library would use. Than the user could override it if needed. I think from the user perspective this will give enough power to the user of the library to archive all goals which are usually needed.

    interface ScalarStyleLookUpStrategy{
        DumperOptions.ScalarStyle overrideScalarStyle(ScalarEvent event, DumperOptions.ScalarStyle suggestedScalarStyle);
    }
    

  8. Andrey Somov

    It looks like the whole change is not simple. Feel free to make a proposal.

    I am also considering changing the API allowing to provide your own Emitter (which can override some methods). But this is also not sweet.

  9. Andrey Somov

    Dear Florian, if you do not suggest a complete proposal, we will not implement it.
    I will try to implement it for the SnakeYAML Engine project, where we have more flexibility.

  10. Log in to comment