2015-09-02 26 views
3

我正在編寫一個函數以獲得來自JSONObject的條目。由於它是JSON,因此輸入名稱的輸入可能存在或可能不存在,所以函數返回Option,當Try失敗時,或者如果值爲NULL,則成功返回None。該函數無法編譯和錯誤返回類型的錯誤。按預期方式推斷出的Scala選項類型

def tryGet[T](jsonObject: JSONObject, name: String): Option[T] = { 
    Try(jsonObject.get(name)) 
    .map(x => if(JSONObject.NULL.equals(x)) None else x.asInstanceOf[T]) 
    .toOption 
} 

錯誤:

Expression of type Option[Any] doesn't conform to expected type Option[T]

有人能告訴我,我做錯了什麼嗎?另外,這是解決問題的慣用方法嗎?

更新:

更改爲下面的工作

def tryGet[T](jsonObject: JSONObject, name: String): Option[T] = { 
    Try(jsonObject.get(name)) 
     .filter(!JSONObject.NULL.equals(_)) 
     .map(_.asInstanceOf[T]) 
     .toOption 
} 

回答

4

問題是這一行:

.map(x => if(x.equals(null)) None else x.asInstanceOf[T]) 
This has type `Option[Nothing]`^  ^This has type `T` 

您同時擁有一個Option[Nothing],如果在一個T/else語句。 if/else的結果類型是結果類型if和結果類型else的最小上限(最接近的常用類型)。在這種情況下,他們沒有共同之處,但是Any。所以結果是Try[Any]它被toOption轉換爲Option[Any]

如果您確實需要檢查null,請改爲使用filter

def tryGet[T](jsonObject: JSONObject, name: String): Option[T] = 
    Try(jsonObject.get(name)) 
     .map(_.asInstanceOf[T]) 
     .filter(_ != null) 
     .toOption 
0

我不認爲你需要的空檢查,而「無」和「T」是兩個可能的結果在地圖上,所以該類型將被映射到您的代碼中的Any而不是「T」。檢查:

Try(jsonObject.get(name)).map(_.asInstanceOf[T]).toOption 

這時,你可能需要的東西是這樣的:

val NullJson:Option[T] = None 
Try(jsonObject.get(name)).map(x=>if(x.equals(null)) NullJson else Option(x.asInstanceOf[T])).toOption.flatten 
+0

是的,我嘗試過了,它拋出「在線程異常‘主要’java.lang.ClassCastException:org.json.JSONObject $空不能轉換爲java.lang.String」,因爲它正試圖在運行時將一個null投射到String。 – broun

+1

@broun你應該寫出你使用的是哪個json庫。我認爲你的json庫沒有返回null,而是返回非null對象org.json.JSONObject $ Null' – ymonad

+0

是的,只是認爲它返回了一個自定義的NULL類型。我正在檢查java空,而不是 – broun

相關問題