2017-06-15 57 views
0

我想修改Groovy中的JSONObject的元類,使其像常規Groovy地圖一樣儘可能地表現。當我在元類中實現方法時,在下面的例子中,其中的一些就像JSONObject.metaClass.size一樣簡單。 JSONObject有一個length()方法,我只是將它連接到一個新的size()方法,但有些方法有特殊的含義。例如,要讓下標分配生效,我必須重寫propertyMissing,而不是putAt。它看起來很像每個收集操作,collect,findAll等都很相似。使用Groovy metaClass實現特殊方法

我的第一個問題是什麼特殊的方法,我需要重寫在這種情況下,使每個()的工作?我的第二個問題是我如何自己找出答案?有沒有參考的地方有從MOP獲得特殊待遇的方法?我試着看着groovy核心的源代碼,但那裏有很多,我不知道從哪裏開始。

JSONObject.metaClass.propertyMissing = { String name, newValue -> delegate.put(name, newValue) } 
JSONObject.metaClass.size = { -> delegate.length() } 
JSONObject.metaClass.each = { cl -> delegate.keys().collectEntries{ [(it): delegate[it] ]}.each(cl) } 

def json = new JSONObject() 
json['a'] = 999 
json.b = 2.2 
json['c'] = 'the letter C' 
println json['a']   // Prints 999 
println json['b']   // Prints 2.2 
println json.c    // 'the letter C' 
println json.size()   // Prints 3 

//No signature of method: ... $__spock_feature_0_0_closure4.doCall() is applicable 
json.each{ k,v -> println "$k = $v"} 
+0

其中的JSONObject?你能給全名嗎? – daggett

+0

org.json.JSONArray和org.json中的org.json.JSONObject:json:20160810' –

回答

2
@Grab(group='org.json', module='json', version='20160810') 

import org.json.JSONArray 
import org.json.JSONObject 

JSONObject.metaClass.each={Closure c-> 
    delegate.keys().each{ k-> c(k, delegate.get(k)) } 
} 

JSONObject.metaClass.setProperty={String k, Object v-> 
    delegate.put(k,v) 
} 

JSONObject.metaClass.getProperty={String k-> 
    delegate.get(k) 
} 

JSONObject.metaClass.size = { -> delegate.length() } 

def json = new JSONObject() 
json['a'] = 999 
json.b = 2.2 
json['c'] = 'the letter C' 
println json['a']   // Prints 999 
println json['b']   // Prints 2.2 
println json.c    // 'the letter C' 
println json.size()   // Prints 3 

//No signature of method: ... $__spock_feature_0_0_closure4.doCall() is applicable 
json.each{ k,v -> println "$k = $v"} 

輸出:

999 
2.2 
the letter C 
3 
a = 999 
b = 2.2 
c = the letter C 
+0

That works :)謝謝!我想我正在或多或少地以正確的方式接近它,但我沒有正確地編寫每個閉包。 –