2017-08-30 2 views
1

JacksonによるJSONデータのデコードを行うアプリケーションがいくつかあります(実際にはいくつかあります)。データはMapまたはArrayList(JSON配列の場合)のいずれかに表示されます。これらのストリームに含まれるデータは構造化されていないため、変更されません。ClojureのAssociative AbstractionをJavaライブラリタイプに拡張する

私はこれらのオブジェクトのネストされたプロパティにアクセスするClojureコードを所有しています。理想的には、Associative抽象化をこれらのJava型に拡張して、get-inがその上で動作するようにしたいと考えています。次のようなものがあります:

(extend-protocol clojure.lang.Associative 
    java.util.Map 
    (containsKey [this k] (.containsKey this k)) 
    (entryAt [this k] (when (.containsKey this k) 
        (clojure.lang.MapEntry/create k (.get this k)))) 
java.util.ArrayList 
    (containsKey [this k] (< (.size this) k)) 
    (entryAt [this k] (when (.containsKey this k) 
        (clojure.lang.MapEntry/create k (.get this k))))) 

これには2つの問題があります。最初にアソシエイティブはプロトコルではありません(もしそうなら、それはうまくいくでしょう)。もう一つは、タイプが既に定義されているため、私はdeftypeをAssociativeに追加できません。

私はClojureのJVM interopの部分でかなり新しくなっています。私が見ていない方法はありますか?または、Associativeをラップし、私が逃したget-inと動作するプロトコルがありますか?

ありがとうございます!

答えて

2

あなたがしたいエクステンションの半分は既に行われていて、残りの半分はできないという答えです。 get-in関数はgetを呼び出し、clojure.lang.RT/getを呼び出します。これはclojure.lang.RT/getFromを呼び出し、最初の引数がMapの場合はjava.util.Map/getを呼び出します。あなたが任意のJava Mapを持っているのであれば、その後、get-in作品(私はdotoドキュメンテーション文字列から直接この例を借りています):

(let [m (doto (new java.util.HashMap) (.put "a" 1) (.put "b" 2))] 
    [(get-in m ["b"]) 
    (get-in m ["a"])]) 
;;=> [2 1] 

はしかし、ClojureのはRandomAccessをサポートListのためget実装を持っていません。あなたないその独自のgetを書くことができます:

(ns sandbox.core 
    (:refer-clojure :exclude [get]) 
    (:import (clojure.lang RT) 
      (java.util ArrayList List RandomAccess))) 

(defn get 
    ([m k] 
    (get m k nil)) 
    ([m k not-found] 
    (if (and (every? #(instance? % m) [List RandomAccess]) (integer? k)) 
    (let [^List m m 
      k (int k)] 
     (if (and (<= 0 k) (< k (.size m))) 
     (.get m k) 
     not-found)) 
    (RT/get map key not-found)))) 

例:

(get (ArrayList. [:foo :bar :baz]) 2) 
;;=> :bar 

それはあなたのカスタムget機能を使用するので、次にあなたがget-inの実装をコピーすることができます。

その後、あなたが書いたコードのすべてのビットがあなたget-inではなく、Clojureののget-inを使用する必要があり、すでにClojureののgetうを使用して他のコードになるので、私は、これはしかし、あなたが望むものではないかなり確信していますまだArrayListで動作しません。私はあなたの問題に本当に良い解決策があるとは思わないが、残念なことに。

+0

サムに感謝、本当にこの問題の良い解決法はないと聞くと便利です。私は非常に幸運なことに、実際にはすべてゲットインのための少数のコールサイトに沸き立っており、現在同様のアプローチをとっています。私はおそらくそれをさらにスリムにし、RTを利用する/あなたの提案を得る。 ありがとう! – Cody

関連する問題