json ドキュメント内の文字列要素の単純な配列を、genson を使用して Bean 内にある Java リストに変換しようとしています。これが自動的に行われることを期待していましたが、機能していません。何か不足していますか?
これが私のJson-Stringです:
{"id":12345,"permissions":["READ_XX","WRITE_XX"]}
そして、これが私のオブジェクトの出力であり、私のアクセス許可リストが入力されていないことを示しています:
DefaultRole [id=12345, name=null, permissions=[]]
私の DefaultRole クラスは次のようになります。
public class DefaultRole implements Role
{
public Id id = null;
@XmlElementWrapper(name = "permissions")
@XmlElement(name = "permission")
private List<String> permissions = Lists.newArrayList();
@Inject
public DefaultRole()
{
}
[...]
JAXB アノテーションは XML 変換専用です。彼らはここで役割を果たすべきではありません。
次のような Genson オブジェクトを作成しています。
Genson genson = new Genson.Builder()
.setWithClassMetadata(false)
.setWithBeanViewConverter(true)
.setWithDebugInfoPropertyNameResolver(true)
.setSkipNull(true)
.create();
私の逆シリアル化呼び出し:
genson().deserialize(jsonString, DefaultRole.class)
JSON文字列配列をBean内にあるJava Listオブジェクトに逆シリアル化する方法についてのヒントはありますか?
編集 [部分的に解決 - まだ 1 つの質問が未解決]
私は今、さらに一歩を踏み出しました。ルーツに戻り、単純に文字列のリストを持つ基本的な Bean から始めました。そして、初めて期待どおり、これは機能します。前のオブジェクトとの主な違いは、これが Bean 仕様に従っていることです。もう 1 つのオブジェクト (DefaultRole) は fluid-object-pattern に従います (それが正しい定義かどうかはわかりません)。基本的に、setter メソッドが void である代わりに、オブジェクトを返すので、次の値を流動的な方法で簡単に設定できます。
したがって、これは機能します:
public void setPermissions(List<String> permissions)
{
this.permissions = permissions;
}
これは動作しません:
public Role setPermissions(List<String> permissions)
{
this.permissions = permissions;
return this;
}
他の誰かがこれに遭遇しましたか?すべてのBeanをBean仕様に準拠するように切り替える代替手段は何ですか? セッターメソッドを使用する代わりに、純粋なフィールドレベルの人口を使用する唯一のオプションはありますか?
編集 [ほぼ解決済み]
こんにちは、私が行ったことを理解するためにコードが必要な質問にどのように答えるのが最善かわかりません。
とにかく、あなたの助けをどうもありがとう。私は、私が探していたタイプのものである 3 番目のオプションが本当に気に入っています。残念ながら、「型クラス xxx.DefaultRole のコンストラクターが見つかりませんでした」というエラーが表示されます。あなたの答えであなたが言ったことによると、これは Trilean.UNKNOWN を返すときに検索が続行されるときに発生しないはずです。
次のコードを genson-builder に追加しています。
.set(new BeanMutatorAccessorResolver.BaseResolver()
{
@Override
public Trilean isMutator(Method method, Class<?> fromClass)
{
if (Reflect.isSetter(method))
return Trilean.TRUE;
else
return Trilean.UNKNOWN;
}
})
私の Reflect.isSetter(method) は次のようになります (コードはここから適応: http://www.asgteach.com/blog/?p=559 ):
public static boolean isSetter(Method method)
{
return Modifier.isPublic(method.getModifiers()) &&
(method.getReturnType().equals(void.class) || method.getReturnType().equals(method.getDeclaringClass())) &&
method.getParameterTypes().length == 1 &&
method.getName().matches("^set[A-Z].*");
}
BaseResolver は、実装されていないすべてのものに対して Trilean.UNKNOWN を返します。したがって、標準ロジックを使用してコンストラクターを見つける必要があります。
編集 [解決済み]
完全を期すために、実際に機能するコードを投稿します。
public static final Genson genson()
{
Genson genson = new Genson.Builder()
.setSkipNull(true)
.setWithClassMetadata(false)
.setWithDebugInfoPropertyNameResolver(true)
.setWithBeanViewConverter(true)
.with(new BeanMutatorAccessorResolver.BaseResolver()
{
@Override
public Trilean isMutator(Method method, Class<?> fromClass)
{
if (Reflect.isSetter(method))
return Trilean.TRUE;
else
return Trilean.UNKNOWN;
}
})
.create();
return genson;
}
ここで、「.set(new BeanMutatorAccessorResolver.BaseResolver()」を「.with(new BeanMutatorAccessorResolver.BaseResolver()」) に置き換える必要があることに注意することが重要です (「set」ではなく「with」に注意してください)。それ以外の場合、標準のリゾルバーは使用されなくなり、コンストラクターが見つからなくなったというエラーが発生します。
isSetter メソッドは次のようになります。
public static boolean isSetter(Method method)
{
return Modifier.isPublic(method.getModifiers())
&& (method.getReturnType().equals(void.class) || method.getReturnType().isAssignableFrom(method.getDeclaringClass()))
&& method.getParameterTypes().length == 1
&& method.getName().matches("^set[A-Z].*");
}
ここで、return-type と declaring-class を比較するときに、もともと「isAssignableFrom」ではなく「equals」を使用していたことに注意することが重要です。これは、戻り値の型が宣言されているクラスとまったく同じクラスである場合にのみ機能します。ただし、戻り値としてインターフェイスを使用する場合は機能しなくなります。代わりに "method.getReturnType().isAssignableFrom(method.getDeclaringClass())" を使用すると、これはインターフェイス (スーパー インターフェイスを含む) でも機能します。
ありがとう、マイケル