使用transform函数对AST进行后处理以重命名json字段名的奇怪行为
很可能我做错了,但事情是这样的。我使用lift json将json响应字符串转换为对象。我得到的响应字符串中有一些字段的名称,这些字段在Scala中不是最好使用的,例如option。我想编写一个“helper”函数,它几乎只是JValue.transform的包装器:使用transform函数对AST进行后处理以重命名json字段名的奇怪行为,json,scala,transform,rename,lift,Json,Scala,Transform,Rename,Lift,很可能我做错了,但事情是这样的。我使用lift json将json响应字符串转换为对象。我得到的响应字符串中有一些字段的名称,这些字段在Scala中不是最好使用的,例如option。我想编写一个“helper”函数,它几乎只是JValue.transform的包装器: def renameFields(originalJson : JValue, oldFieldName : String, newFieldName : String): JValue = { originalJson
def renameFields(originalJson : JValue, oldFieldName : String, newFieldName : String): JValue = {
originalJson transform { case JField(oldFieldName,x) => JField(newFieldName, x)}
}
下面是我正在使用的示例响应字符串和JObject:
scala> val jstring = """ { "aisle" : 1, "bin" : 1, "hasWhat" : [{ "id" : 4, "name" : "Granny", "color" : "green"}, { "id" : 4, "name" : "Fuji", "color" : "red"}] }"""
jstring: java.lang.String = { "aisle" : 1, "bin" : 1, "hasWhat" : [{ "id" : 4, "name" : "Granny", "color" : "green"}, { "id" : 4, "name" : "Fuji", "color" : "red"}] }
scala> val json = parse(jstring)
json: net.liftweb.json.JsonAST.JValue = JObject(List(JField(aisle,JInt(1)), JField(bin,JInt(1)), JField(hasWhat,JArray(List(JObject(List(JField(id,JInt(4)), JField(name,JString(Granny)), JField(color,JString(green)))), JObject(List(JField(id,JInt(4)), JField(name,JString(Fuji)), JField(color,JString(red)))))))))
如果使用此函数,所有字段名称最终都会更改:
scala> Util.renameFields(json,"aisle","row")
res2: net.liftweb.json.JsonAST.JValue = JObject(List(JField(row,JInt(1)), JField(row,JInt(1)), JField(row,JArray(List(JObject(List(JField(row,JInt(4)), JField(row,JString(Granny)), JField(row,JString(green)))), JObject(List(JField(row,JInt(4)), JField(row,JString(Fuji)), JField(row,JString(red)))))))))
我真正想要的是:
scala> json transform { case JField("aisle",x) => JField("row",x) }
res3: net.liftweb.json.JsonAST.JValue = JObject(List(JField(row,JInt(1)), JField(bin,JInt(1)), JField(hasWhat,JArray(List(JObject(List(JField(id,JInt(4)), JField(name,JString(Granny)), JField(color,JString(green)))), JObject(List(JField(id,JInt(4)), JField(name,JString(Fuji)), JField(color,JString(red)))))))))
那么…我做错了什么?提前谢谢
-仍然是新手我想你所缺少的是关于
oldFieldName的反勾号
:
scala> def renameFields(originalJson : JValue, oldFieldName : String, newFieldName : String): JValue = originalJson transform { case JField(`oldFieldName`,x) => JField(newFieldName, x)}
renameFields: (originalJson: net.liftweb.json.JsonAST.JValue,oldFieldName: String,newFieldName: String)net.liftweb.json.JsonAST.JValue
scala> val jstring = """ { "aisle" : 1, "bin" : 1, "hasWhat" : [{ "id" : 4, "name" : "Granny", "color" : "green"}, { "id" : 4, "name" : "Fuji", "color" : "red"}] }"""
jstring: java.lang.String = { "aisle" : 1, "bin" : 1, "hasWhat" : [{ "id" : 4, "name" : "Granny", "color" : "green"}, { "id" : 4, "name" : "Fuji", "color" : "red"}] }
scala> val json = parse(jstring)
json: net.liftweb.json.JsonAST.JValue = JObject(List(JField(aisle,JInt(1)), JField(bin,JInt(1)), JField(hasWhat,JArray(List(JObject(List(JField(id,JInt(4)), JField(name,JString(Granny)), JField(color,JString(green)))), JObject(List(JField(id,JInt(4)), JField(name,JString(Fuji)), JField(color,JString(red)))))))))
scala> renameFields(json,"aisle","row")
res0: net.liftweb.json.JsonAST.JValue = JObject(List(JField(row,JInt(1)), JField(bin,JInt(1)), JField(hasWhat,JArray(List(JObject(List(JField(id,JInt(4)), JField(name,JString(Granny)), JField(color,JString(green)))), JObject(List(JField(id,JInt(4)), JField(name,JString(Fuji)), JField(color,JString(red)))))))))
在没有反勾号的情况下,
case JField(oldFieldName,x)
表示“将我找到的作为JField
名称的任何值绑定到新变量oldFieldName
”,因此原始的oldFieldName
变量被隐藏。在oldFieldName
周围有反勾号,表示您只想匹配一个JField
,其名称是oldFieldName(在此处插入墙bash)的值。缺少反勾号/前勾号/引号的诅咒。谢谢Steve,我从来没有想过在方法中使用任何类型的勾号或引号。出于好奇,你是怎么知道要这么做的?我想可能是因为阅读了这篇文章,特别是“在模式匹配中使用以小写字母开头的标识符”的答案提到了反勾号。再次感谢Steve!这是一个非常有用的帖子。