2017-09-26 6 views
0

Apex 코드의 REST 서비스 응답에서 YAML 문자열을 얻었고이를 구문 분석하고 Salesforce 객체 컬렉션으로 변환하는 것과 비슷한 방법을 찾습니다.Salesforce Apex에서 YAML 객체를 구문 분석하는 방법

는 예를 들어, 내가 문자열과 같은 YAML을 얻을 :

--- 
item: 
    - 
    title: A Grief Observed 
    author: C. S. Lewis 
    author_by_last: Lewis, C. S. 
    isbn: "0060652381" 
    publisher: ZOND 
    on_hand: "5" 
    in_pub_date: 2001-01-01 
    - 
    title: "Grief Sanctified: From Sorrow to Eternal Hope: Including Richard Baxter's Timeles" 
    author: J. I. Packer 
    author_by_last: Packer, J. I. 
    isbn: "1581344406" 
    publisher: CROSS 
    on_hand: "5" 
    in_pub_date: 2002-09-01 

그리고 책 오브젝트의리스트로 변환하고 싶습니다. JSON으로 작업했을 때 역 직렬화 기능을 제공 한 JSON class을 사용했는데 Salesforce가 YAML 처리와 비슷한 기능을 제공하는지 알고 싶습니다.

+1

그들은 그렇지 않습니다. 수동으로 구문 분석해야합니다. –

답변

1

참고 :이 내용은 내가 same question on the Salesforce SE site에 준 응답에서 복사/붙여 넣기됩니다.

아니요, 작성 (API v41.0) 할 때 Salesforce에는 YAML을 만들거나 구문 분석 할 수있는 기본 제공 기능이 없습니다. 즉, 자신 만의 빌드 (또는 Java와 같은 다른 언어의 기존 언어를 Apex에 적용)해야합니다.

범용 파서 (유효한 YAML을 처리 할 수있는 것)를 찾고 있지 않으며 변경하려는 데이터의 형식을 기대하지 않으면 도메인 별 파서를 작성해야합니다. 너무 많은 일이 아니야.

내가 XML로 작업 할 때, 나는받는 스키마를 개별 apex 클래스로 분해하고 각각의 구문 분석 메소드를 작성하는 것을 좋아한다. 이렇게하면 파서를 관리하기가 쉽습니다. 유사한 접근법이 YAML로 취해질 수 있습니다.

// Yes, the need for this BookCollection object is debatable (it's mainly just storing 
// a List). 
// Encapsulating the parsing makes it worth being made into a class (in my mind). 
public class BookCollection{ 
    // The class variables for each level mimic the data stored on each level 
    // of the schema of your incoming data. 
    // This will become more apparent later. 
    public List<Book> item; 

    public BookCollection(String input){ 
     item = new List<Book>(); 

     // At this level, all we're concerned about is finding the individual books. 
     // Once we find a book, we pass it down to the next level of parsing (and 
     // add the result to our list) 
     // YAML uses whitespace to denote structure, so we need to take that into 
     // account when splitting. 
     // The regex here looks for two spaces, a hyphen, one space, a newline. 
     // Everything after that (up to the next ' - \n' or EOF) is book data. 

     // String.split() will return 'item:' as the first part. 
     // That isn't part of the data for a book, so we'll want to remove that. 
     List<String> bookStringsList = input.split(' - \n'); 
     bookStringsList.remove(0); 

     for(String bookString :bookStringsList){ 
      Book currentBook = new Book(bookString); 
      item.add(currentBook); 
     } 
    } 
} 

public class Book{ 
    // Now it should be more apparent that we're mimicking the structure of the 
    // incoming data. 
    String title; 
    String author; 
    String author_by_last; 
    String isbn; 
    String publisher; 
    Integer on_hand; 
    Date in_pub_date; 

    public Book(String input){ 
     // On this level of parsing, we have actual data to work with. 
     // Our job here is to find all of the key:value pairs, and cast them to 
     // their appropriate types. 
     for(String keyAndValue :input.split(' \n')){ 
      String key, value; 
      List<String> kvSplit = keyAndValue.split(':'); 
      key = kvSplit[0]; 
      // Double quotes are likely to mess things up, so remove them. 
      value = kvSplit[1].replace('"', ''); 

      // There's probably a more elegant way to handle this than a big 'ol 
      // if/else if chain...but this'll work 
      if(key == 'title'){ 
       this.title = value; 
      } else if(key == 'author'){ 
       this.author = value; 
      } else if(key == 'author_by_last'){ 
       this.author_by_last = value; 
      } else if(key == 'isbn'){ 
       this.isbn = value; 
      } else if(key == 'publisher'){ 
       this.publisher = value; 
      } else if(key == 'on_hand'){ 
       // String -> Integer is pretty easy, we can use Integer.valueOf() 
       this.on_hand = Integer.valueOf(value); 
      } else if(key == 'in_pub_date'){ 
       // Dates are a bit tricky. 
       // Salesforce wants them in YYYY-MM-DDThh:mm:ssZ format, or the format 
       // used in your locale (for parse() or valueOf()). 
       // Given our data, it's easiest to simply generate a new date instance 
       List<String> dateParts = value.split('-'); 

       this.in_pub_date = Date.newInstance(dateParts[0], dateParts[1], dateParts[2]); 
      } 
     } 
    } 
} 

이러한 클래스를 사용하는 것은 매우 간단합니다. 그러나 일부 추가 설정이 필요합니다.

// Your YAML, from some source 
String myYAML = blackBox.getData(); 

// Break up your YAML's documents before attempting to parse each one. 
List<String> documents = myYAML.split('---\n'); 

// The first result string will likely always be empty, so we can remove that. 
documents.remove(0); 

// This is the simple case where we know we're only dealing with a single document. 
// If you had multiple documents in a single YAML string, you would (hopefully) 
// be able to tell which type of document you were working with (and you'd 
// need additional logic to determine which parser class to send the data to). 
BookCollection myBooks = new BookCollection(documents[0]);