2015-11-18 70 views
0

我無法爲Json4s編寫自定義序列化程序來處理以下情況。我有case類:Json4s超類的序列化

trait Condition 
case class BasicExpression (field:String, operator:String, value:String) extends Condition 
case class BooleanExpression (val leftExpr: Condition, val logicalOperator:String, 
    val rightExpr: Condition) extends Condition 

,我希望能夠讀取JSON兩個BasicExpressionBooleanExpression使用,例如:

var jsonStringBasic:String = """ {"field":"name","operator":"=","value":"adam"}"""; 
var jsonStringBoolean:String = """{"leftExpr":{"leftExpr":{"field":"field1", "operator":"=", "value":"value1"}, "logicalOperator":"AND", "rightExpr":{"field":"field2","operator":">","value":"500"}}, "logicalOperator":"AND", "rightExpr": {"field":"field3","operator":"<","value":"10000"}}"""; 
var jValueBasic:JValue = parse(jsonStringBasic, false); 
var readCBasic = jValueBasic.extract[Condition]; 

我明白了定製串行器是如何工作的讀取BasicExpression ,並且我可以使用SimpleTypeHints,但不必爲每個Condition都膨脹JSON。我也可以嘗試extract[BooleanExpression],如果失敗嘗試extract[BasicExpression],但看起來很難看。是否可以編寫自定義序列化程序來處理這個事實:BooleanCondition本身將包含另一個Condition,因此我可以extract[Condition]

回答

0

設法讓CustomSerializer工作,所以它可以遞歸調用本身,在布爾表達式的情況下,如下:

class ConditionSerialiser extends CustomSerializer[Condition](format => (

{ 
    def deserialiseCondition:PartialFunction[JValue, Condition]= { 
     case JObject(List(JField("field", JString(field)), JField("operator", JString(operator)), JField("value", JString(value)))) => BasicStringExpression(field, operator, value) 
     case JObject(List(JField("field", JString(field)), JField("operator", JString(operator)), JField("value", JInt(value)))) => BasicNumericExpression(field, operator, value.doubleValue) 
     case JObject(List(JField("field", JString(field)), JField("operator", JString(operator)), JField("value", JDouble(value)))) => BasicNumericExpression(field, operator, value) 
     case JObject(List(JField("leftExpr", leftExpr), JField("logicalOperator", JString(logicalOperator)), JField("rightExpr", rightExpr))) => BooleanExpression(deserialiseCondition(leftExpr), logicalOperator, deserialiseCondition(rightExpr)) 
    } 
    deserialiseCondition 
}, 
{ 
    case bse: BasicStringExpression => JObject(List(JField("field", JString(bse.field)), JField("operator", JString(bse.operator)), JField("value", JString(bse.value))))  
} 
)) 
0

更好的解析JSON,你可以試試這個:

import com.google.gson.Gson; 
import com.google.gson.GsonBuilder; 


public class GsonUtils { 

public static String defaultDateTimeFormat = "yyyy-MM-dd'T'HH:mm:ssZ"; 
private static GsonBuilder gsonBuilder = new GsonBuilder().setDateFormat(defaultDateTimeFormat); 

/*** 
* Creates a GSON instance from the builder with the default date/time format 
* 
* @return the GSON instance 
*/ 
public static Gson createGson() { 
    // Create with default params 
    gsonBuilder = gsonBuilder.setDateFormat(defaultDateTimeFormat); 
    return gsonBuilder.create(); 
} 

/*** 
* Creates a GSON instance from the builder specifying custom date/time format 
* 
* @return the GSON instance 
*/ 
public static Gson createGson(String dateTimeFormat) { 
    // Create with the specified dateTimeFormat 
    gsonBuilder = gsonBuilder.setDateFormat(dateTimeFormat); 
    return gsonBuilder.create(); 
} 

}

,並使用它像這樣

var String = """ {"field":"name","operator":"=","value":"adam"}"""; 

    Type collectionType = new TypeToken<YOUR_CLASS>() {}.getType(); 
    YOUR_CLASS iii= GsonUtils.createGson().fromJson(jsonStringBasic, collectionType); 
+0

感謝您的建議 - 我轉向Gson了一下,但當Gson不支持Scala列表或地圖時遇到了更多問題,於是我回到Json4s,想出瞭如何編寫serialiser – adambriffett