2017-03-21 2 views
0

서비스를 구축 중입니다. 파일에서 config를 읽어야합니다. 우리는 현재 YAML을 deserialize하기 위해 YAML과 Jackson을 사용하고 있습니다. 우리는 YAML 파일이 다른 YAML 파일을 상속/연장해야하는 상황을 가지고 있습니다. 예 :상속을 지원하는 YAML 또는 JSON 라이브러리

extends: base.yaml 

appName: my-awesome-app 

... 

따라서 구성의 일부는 base.yaml에 저장됩니다. 이 라이브러리를 지원합니까? 두 개 이상의 파일을 상속 할 수있는 경우 보너스 포인트. YAML 대신 JSON을 사용할 수 있습니다.

+0

[HOCON] (https://github.com/typesafehub/config#features-of-hocon)에는'include' 구문이 있습니다. –

답변

1

JSON이나 YAML에는 파일을 포함 할 수 없습니다. 당신이 무엇을하든 base.yaml과 실제 파일을 함께 모으는 전처리 단계가 될 것입니다.

이 일의 원유 방법은 다음과 같습니다

#include base.yaml 
appName: my-awesome-app 

이이 파일합시다. 로드가 끝나면 첫 번째 줄을 읽은 다음 #include으로 시작하면 포함 된 파일의 내용으로 바꿉니다. 이것을 재귀 적으로 수행해야합니다. 이것은 기본적으로 C 전처리 기가 C 파일로 수행하고 포함하는 것입니다.

단점은 다음과 같습니다 두 파일이 유효 YAML을 경우에도

  • , 결과가되지 않을 수도 있습니다.
  • 두 파일 중 하나에 지시문 끝 또는 문서 끝 마커 (--- 또는 ...)가 포함되어 있으면 하나의 파일에 2 개의 개별 문서가 생성됩니다.
  • 파일 내에서 base.yaml의 값을 대체 할 수 없습니다.

따라서 대안은 실제로 YAML 구조에서 작동하는 것입니다. 이를 위해서는 YAML 파서 (귀하의 경우 SnakeYAML)의 API가 필요하고 파일을 파싱해야합니다.

!include : base.yaml 
appName: my-awesome-app 

내가 어떤 노멀 매핑 키 이름 충돌이되지 않도록 민간 태그 !include을 사용 :이 코드는 구문 분석

private Node preprocess(final Reader myInput) { 
    final Yaml yaml = new Yaml(); 
    final Node node = yaml.compose(myInput); 
    processIncludes(node); 
    return node; 
} 

private void processIncludes(final Node node) { 
    if (node instanceof MappingNode) { 
     final List<NodeTuple> values = ((MappingNode) node).getValue(); 
     for (final NodeTuple tuple: values) { 
      if ("!include".equals(tuple.getKeyNode().getTag().getValue())) { 
       final String includedFilePath = 
         ((ScalarNode) tuple.getValueNode()).getValue(); 
       final Node content = preprocess(new FileReader(includedFilePath)); 
       // now merge the content in your preferred way into the values list. 
       // that will change the content of the node. 
      } 
     } 
    } 
} 

public String executePreprocessor(final Reader source) { 
    final Node node = preprocess(source); 
    final StringWriter writer = new StringWriter(); 
    final DumperOptions dOptions = new DumperOptions() 
    Serializer ser = new Serializer(new Emitter(writer, dOptions), 
            new Resolver(), dOptions, null); 
    ser.open(); 
    ser.serialize(node); 
    ser.close(); 
    return writer.toString(); 
} 

이 같이 포함되어 있습니다 : 당신은 작성 API를 사용해야합니다. 공백을 두려워하는 !include. 내가 포함 된 파일을 병합하는 코드를 제공하지 않았다. 왜냐하면 나는 당신이 어떻게 중복 된 매핑 키를 다루고 싶어하는지 알지 못하기 때문이다. 그래도 구현하기가 어렵지 않아야합니다. 버그를 인식하고,이 코드를 테스트하지 않았습니다.

결과 문자열은 Jackson의 입력 일 수 있습니다.