2016-03-01 58 views
1

在Scala中,我有以下的數據結構(Item名稱始終相同Container內是唯一的):播放的Json寫入:Scala的SEQ到JSON對象

case class Container(content: Seq[Item]) 
case class Item(name: String, elements: Seq[String]) 

實施例實例:

val container = Container(Seq(
    Item("A", Seq("A1", "A2")), 
    Item("B", Seq("B1", "B2")) 
)) 

我想要做的是定義一個產生以下JSON的Writes[Container]

{ 
    "A": ["A1", "A2"], 
    "B": ["B1", "B2"] 
} 

I guess一個可能的解決方案可能是將Container(Seq[Item])轉換爲Map[String, Seq[String]],其中每個鍵對應於項目的名稱和項目元素的值,並讓API執行其餘的操作(可能會隱式寫入映射,閱讀JSON時至少是這種情況)。

但是:此方法爲每個Container創建一個新的Map,除了生成JSON之外沒有其他目的。有很多Container情況下需要被轉化爲JSON,所以我認爲這種做法是相當昂貴的。我還能怎麼做?

回答

2

我不認爲你應該不必擔心速度在這裏(或至少驗證它是擔心之前的一個問題),並轉換成地圖可能是最簡單的選擇。另一種,這很可能不執行任何更好的,就是:

val customWrites: Writes[Container] = new Writes[Container] { 
    override def writes(container: Container): JsValue = { 
    val elems = container.content.map(
     elem => elem.name -> Json.toJsFieldJsValueWrapper(elem.elements)) 
    Json.obj(elems: _*) 
    } 
} 

(顯式轉換爲JsValueWrapper - 這通常是隱含的 - 似乎有必要在這方面的原因,我不完全理解或有時間鑽研。This answer有一些細節。)

一個優點這種方法的是,它會處理Item對象名稱重複的(這當然是合法的JSON,但會導致衝突與地圖。)

+0

你關於表演可能是正確的。但是,您的解決方案不僅允許重複名稱,而且還保留更好的元素順序,謝謝! – ceran