2017-01-03 7 views
1

私は私のコントローラでこのメソッドを持っているのヒンティングなし「InterfaceClassのインスタンスを作成することはできません」:克服親

@RequestMapping(method = RequestMethod.POST) 
InterfaceClass insert(@RequestBody InterfaceClass interfaceClass) { 

    // Do something 
} 

私は取得していますエラーは非常に簡単かつ自明である:

Can not construct instance of InterfaceClass: abstract types either need to be mapped to concrete types, have custom deserializer, or contain additional type information. 

基本的には、具体的な実装がInterfaceClassClassImplであることをSpringに伝える必要があります。

私が試した:なし程度の

@JsonRootName("InterfaceClass") 
public class ClassImpl implements InterfaceClass { 
} 

を。私は@JsonTypeInfoを親インターフェイスクラスとして使用できませんInterfaceClassClassImplを意識してはならず、別のモジュールにあります。私も試してみました何:

は抽象AbstractClassInterfaceClassを実装して置く:

@JsonDeserialize(as = AbstractClass.class) 

InterfaceClassの上に。その後、AbstractClassClassImplに拡張します。また試み

Can not construct instance of InterfaceClass: abstract types either need to be mapped to concrete types, have custom deserializer, or contain additional type information. 

:エラーは、単になる

public class ControllerClass<E extends InterfaceClass> { 

    @RequestMapping(method = RequestMethod.POST) 
    InterfaceClass insert(@RequestBody E interfaceClass) { 
     InterfaceClass object = (InterfaceClass) interfaceClass; 
    } 
} 

を、これはもたらす:予想通り

java.lang.ClassCastException: java.util.LinkedHashMap cannot be cast to InterfaceClass 

InterfaceClassまたはAbstractClassの具体的な実装が1つしかないため、クラスパスにClassImplという具合に実装されているため、Springブートでコンポーネント検出を処理することが本当に期待されていました。多分私は何か間違っているのでしょうか? InterfaceClassの実装がどこにあるかを明示的に示唆することなく、これを克服するにはどうすればよいですか(例:@JsonDeserializeなど)?

答えて

2

解決策1 - 動的にあなたが動的にサブタイプを定義することができ、サブタイプ

を登録します。インターフェイス上で

1、識別子として使用されるJSONフィールド(@type)を定義します。

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, 
       include = JsonTypeInfo.As.PROPERTY, property = "@type") 
public interface InterfaceClass { 
} 

2. [追加 "@type" フィールドあなたのJSONペイロードに

動的
{ 
    ... 
    "@type": "someName" 
} 

2.登録intefaceをのサブタイプ:

@Bean 
public Jackson2ObjectMapperBuilder objectMapperBuilder() { 
    Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder() { 
     public void configure(ObjectMapper objectMapper) { 
      objectMapper.registerSubtypes(ClassImpl.class); 
      super.configure(objectMapper); 
     }; 
    }; 
    return builder; 
} 

4。あなたの具体的なクラスの "@type" の名前を指定します(オプション):

//Optional, otherwise uses the Simple class name (ie: 'ClassImpl') 
@JsonTypeName("someName") 
public class ClassImpl implements InterfaceClass { 
} 

5.今@RequestBodyとのインターフェースを使用することができます。

@RequestMapping(method = RequestMethod.POST) 
InterfaceClass insert(@RequestBody InterfaceClass interfaceClass) { 
} 

ソリューション2 - @typeフィールドを追加する(たかったりしない)ことができない場合、動的に、あなたもカスタムを定義することができ、カスタムデシリアライザ

を登録

1.カスタムデシリアライザ定義します:実際にClassImplを作成することになり、あなたのインターフェイスのためのデシリアライザ、

@Bean 
public Jackson2ObjectMapperBuilder objectMapperBuilder() { 
    Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder(); 
    builder.deserializerByType(InterfaceClass.class, new ClassImplJsonDeserializer()); 
    return builder; 
} 

class ClassImplJsonDeserializer extends JsonDeserializer<ClassImpl> { 
    @Override 
    public ClassImpl deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException { 
     return jp.readValuesAs(ClassImpl.class).next(); 
    } 
} 

2.動的カスタムデシリアライザを設定します3.インターフェイスから@JsonTypeInfoを削除します。

public interface InterfaceClass { 
} 
関連する問題