티스토리 뷰

Template Engine에서 value path대신 JsonPath의 path를 사용하면 동적으로 Json을 내가 지정한 Template로 변환시킬 수 있다.

PebbleEngine pebbleEngine = new PebbleEngine.Builder()
    .loader(new StringLoader())
    .build();

//member source json
//{
//    "id":1234,
//    "name":"jack",
//    "age":20,
//    "address": {
//    "address1":"kor",
//        "address2":"seoul",
//        "address3":"gangnam"
//    },
//    "phoneNumber":"010-1234-1234",
//    "email":"abcd@google.com"
//}
String memberSourceJson = "{\"id\":1234,\"name\":\"jack\",\"age\":20,\"address\":{\"address1\":\"kor\",\"address2\":\"seoul\",\"address3\":\"gangnam\"},\"phoneNumber\":\"010-1234-1234\",\"email\":\"abcd@google.com\"}";

//member contact template
//{
//    "memberAddress":{{"key.memberAddress.address3"}},
//    "memberPhoneNumber":{{"key.phoneNumber"}},
//    "memberEmail":{{"key.email"}}
//}
String memberContactTemplate = "{\"address\":\"{{key.memberAddress.address3}}\",\"memberPhoneNumber\":\"{{key.phoneNumber}}\",\"memberEmail\":\"{{key.email}}\"}";


DocumentContext sourceDocumentContext = JsonPath.parse(memberSourceJson);

Map<String, Object> map = Maps.newHashMap();
map.put("key", sourceDocumentContext.json());

Writer writer = new StringWriter();
PebbleTemplate pebbleTemplate = pebbleEngine.getTemplate(memberContactTemplate);
pebbleTemplate.evaluate(writer, map);

System.out.println("result: " + writer.toString());

//{
//    "memberAddress":"gangnam",
//    "memberPhoneNumber":"010-1234-1234",
//    "memberEmail":"abcd@google.com"
//}
//result: {"memberAddress":"gangnam","memberPhoneNumber":"010-1234-1234","memberEmail":"abcd@google.com"}
바로위의 예제 코드에서는 JsonPath를 바로 사용했지만 아래와 같이JsonProvider를 사용할 수도 있다.

1. Use JsonPath
DocumentContext sourceDocumentContext = JsonPath.parse(memberSourceJson);
Map<String, Object> map = Maps.newHashMap();
map.put("key", sourceDocumentContext.json());

2. Use JsonProvider
Object source = Configuration.defaultConfiguration().jsonProvider().parse(memberSourceJson);
Map<String, Object> map = Maps.newHashMap(argumentMap);
map.put("key, source);

어떻게 Json이 변경될 수 있을까?

우리가 접하는 Template Engine은 handle bar, freemaker 등등이 있다. 보통 web front에서 많이 접하게 되는데 기본적인 원리는 template은 html 코드 value는 "."으로 구분된 value path를 넣는다. Template Engine은 template을 parsing하고 value의 path를 map에서 찾아와 값을 replace 한다. 위 예제도 동일하다.

  1. JsonPath는 Json을 parsing하여 DocumentContext를 생성한다. 내부적으로 DocumentContext는 map과 거의 비슷하다.
  2. Template Engine은 Template을 parsing하여 Template객체를 생성한다.
  3. DocumentContext.json()을 호출하면 내부에 가지고있는 key-value 형태의 Object를 리턴한다.
  4. Template객체에 json을 파싱한 결과인 key-value Object를 넘겨주면, template에 있는 value path를 이 map에서 찾아 적용한다.

추가적으로 Template Engine은 확장 기능을 제공한다.

아래는 Pebble의 확장 기능인 Function을 생성 / 등록 예제이다.

  1. Function Class를 생성한다.

    import com.mitchellbosecke.pebble.extension.Function;
    import com.google.common.collect.Lists;
    import com.jayway.jsonpath.JsonPath;
    import com.mitchellbosecke.pebble.template.EvaluationContext;
    import com.mitchellbosecke.pebble.template.PebbleTemplate;
    import java.util.List;  
    import java.util.Map;
    
    /**
     * 기본 목적은 특정 Business에 특화되거나, 공통 Util 성격의 Function을 생성하는것이다.
     * 뿐만 아니라 JsonPath를 Pebble Fucntion으로 등록하면,
     * JsonPath와 PebbleFunction에서 지원하는 모든 기능을 사용할 수 있게 된다.
     */
    public class JsonPathPebbleFunction implements Function {  
      @Override  
      public String getFunctionKey() {  
      return "addNamePrefix";  
      }
    
      @Override
      public Object execute(Map<String, Object> args, PebbleTemplate self, EvaluationContext context, int lineNumber)     {
          String jsonPath = (String) args.get("jsonPath");
          Object document = args.get("prefix");
          String prefix = (String) args.get("prefix");
          return JsonPath.read(document, jsonPath) + prefix;
      }
    
      @Override
      public List<String> getArgumentNames() {
          return Lists.newArrayList("jsonPath", "source");
      }
    }
    
  2. Function 객체를 생성하여 등록한다.

    import com.google.common.collect.Maps;  
    import com.mitchellbosecke.pebble.extension.AbstractExtension;  
    import com.mitchellbosecke.pebble.extension.Function;
    
    import java.util.List;  
    import java.util.Map;
    
    public class FunctionExtension extends AbstractExtension {
     public FunctionExtension() {
         this.functionMap = Maps.newHashMap();
         this.functionMap.put("prefixFunction", new PrefixPebbleFunction());
     }
    
     @Override
     public Map<String, Function> getFunctions() {
         return this.functionMap;
     }
    }
  3. Pebble Template Engine에 Function들을 extension으로 추가한다.

    PebbleEngine pebbleEngine = new PebbleEngine.Builder()  
    .loader(new StringLoader())  
    .extension(pebbleFunctionExtension)  
    .build();  

** reference

JsonPath: https://github.com/json-path/JsonPath

Pebble Template Engine: https://pebbletemplates.io/

'Programming > 유용한 라이브러리' 카테고리의 다른 글

Jcommander Parameter  (0) 2020.04.24
Typesafe Config  (1) 2020.04.24
JsonPath  (0) 2020.04.03
MapStruct  (0) 2019.08.30
Guava AsyncEventBus  (0) 2019.02.07
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
«   2024/05   »
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
글 보관함