Muszę użyć go jako TypeReference <Data <T>> () {} ... Ale pojawia się następujący błąd - nie mogę uzyskać dostępu do prywatnego java.lang.class.Class () z java.lang.class. Nie udało się ustawić dostępu. Nie można udostępnić konstruktora java.lang.Class
A jeśli nie wiem, jaka to klasa do czasu uruchomienia? Otrzymam klasę jako parametr podczas działania. Podobnie jak ten public <T> void deSerialize (Class <T> clazz {ObjectMapper mapper = new ObjectMapper (); mapper.readValue (jsonString, new TypeReference <Json <T>> () {});}
Nie możesz tego zrobić: musisz określić typ w pełni rozwiązany, na przykład Data<MyType>. Tjest tylko zmienną i bez znaczenia.
Ale jeśli masz na myśli, że Tbędzie znany, tylko nie statycznie, musisz utworzyć odpowiednik TypeReferencedynamicznie. Inne przywoływane pytania mogą już o tym wspominać, ale powinno to wyglądać mniej więcej tak:
publicData<T> read(InputStream json,Class<T> contentClass){JavaType type = mapper.getTypeFactory().constructParametricType(Data.class, contentClass);return mapper.readValue(json, type);}
A jeśli nie wiem, jaka to klasa do czasu uruchomienia? Otrzymam klasę jako parametr podczas działania. Podobnie jak ten public <T> void deSerialize (Class <T> clazz {ObjectMapper mapper = new ObjectMapper (); mapper.readValue (jsonString, new TypeReference <Json <T>> () {});}
Problem polega na tym, że „Dane” to klasa ogólna. Muszę określić, jaki typ T jest w czasie wykonywania. Parametr clazz jest tym, co robimy w czasie wykonywania. Jak więc wywołać readValue? wywołanie go nowym TypeReference> Json <T>> nie działa Pełne pytanie jest tutaj stackoverflow.com/questions/11659844/…
Pierwszą rzeczą, którą musisz zrobić, jest serializacja, a następnie możesz przeprowadzić deserializację.
więc kiedy robisz serializację, powinieneś użyć, @JsonTypeInfoaby pozwolić Jacksonowi zapisywać informacje o klasach do twoich danych JSON. Oto co możesz zrobić:
Następnie, kiedy deserializujesz, zobaczysz, że jackson zdeserializował twoje dane do klasy, w której trafia twoja zmienna, w rzeczywistości w czasie wykonywania.
nie działa, pojawia się błąd poniżej com.fasterxml.jackson.databind.exc.InvalidTypeIdException: Brak identyfikatora typu podczas próby rozwiązania podtypu [typ prosty, klasa java.lang.Object]: brak właściwości identyfikatora typu „@class” (dla POJO property 'data')
Po prostu napisz metodę statyczną w klasie Util. Czytam Json z pliku. możesz nadać String również readValue
publicstatic<T> T convertJsonToPOJO(String filePath,Class<?> target)throwsJsonParseException,JsonMappingException,IOException,ClassNotFoundException{ObjectMapper objectMapper =newObjectMapper();return objectMapper.readValue(newFile(filePath), objectMapper .getTypeFactory().constructCollectionType(List.class,Class.forName(target.getName())));}
Stosowanie:
List<TaskBean> list =Util.<List<TaskBean>>convertJsonToPOJO("E:/J2eeWorkspaces/az_workspace_svn/az-client-service/dir1/dir2/filename.json",TaskBean.class);
Ciąg JSON, który musi zostać zdeserializowany, będzie musiał zawierać informacje o typie parametru T.
Będziesz musiał umieścić adnotacje Jacksona na każdej klasie, która może być przekazana jako parametr Tdo klasy, Dataaby TJackson mógł odczytać informacje o typie parametru z / zapisać do łańcucha JSON.
Załóżmy, że Tmoże to być dowolna klasa, która rozszerza klasę abstrakcyjną Result.
classData<T extendsResult>{int found;Class<T> hits
}@JsonTypeInfo(use =JsonTypeInfo.Id.NAME, include =JsonTypeInfo.As.WRAPPER_OBJECT)@JsonSubTypes({@JsonSubTypes.Type(value =ImageResult.class, name ="ImageResult"),@JsonSubTypes.Type(value =NewsResult.class, name ="NewsResult")})publicabstractclassResult{}publicclassImageResultextendsResult{}publicclassNewsResultextendsResult{}
Gdy każda klasa (lub ich wspólny nadtyp), która może zostać przekazana jako parametr, T zostanie opatrzona adnotacją, Jackson umieści informacje o parametrze Tw JSON. Taki JSON można następnie deserializować bez znajomości parametru Tw czasie kompilacji.
Ten link do dokumentacji Jacksona mówi o deserializacji polimorficznej, ale jest przydatny również w przypadku tego pytania.
Przypuśćmy, że chcesz przeprowadzić deserializację Data<String> , możesz wykonać:
// the json variable may be a String, an InputStream and so for...JavaType type = mapper.getTypeFactory().constructParametricType(Data.class,String.class);Data<String> data = mapper.readValue(json, type);
Zwróć uwagę, że gdyby klasa zadeklarowała wiele sparametryzowanych typów, nie byłoby to naprawdę trudniejsze:
JavaType type = mapper.getTypeFactory().constructParametricType(Data.class,String.class,Integer);Data<String,Integer> data = mapper.readValue(json, type);
jeśli używasz scala i znasz typ ogólny w czasie kompilacji, ale nie chcesz ręcznie przekazywać TypeReference wszędzie we wszystkich swoich api lachach, możesz użyć następującego kodu (z jacksonem 2.9.5):
def read[T](entityStream:InputStream)(implicit typeTag:WeakTypeTag[T]): T ={//nathang: all of this *crazy* scala reflection allows us to handle List[Seq[Map[Int,Value]]]] without passing// new TypeReference[List[Seq[Map[Int,Value]]]]](){} to the function
def recursiveFindGenericClasses(t:Type):JavaType={
val current = typeTag.mirror.runtimeClass(t)if(t.typeArgs.isEmpty){
val noSubtypes =Seq.empty[Class[_]]
factory.constructParametricType(current, noSubtypes:_*)}else{
val genericSubtypes:Seq[JavaType]= t.typeArgs.map(recursiveFindGenericClasses)
factory.constructParametricType(current, genericSubtypes:_*)}}
val javaType = recursiveFindGenericClasses(typeTag.tpe)
json.readValue[T](entityStream, javaType)}
Używamy plików cookie i innych technologii śledzenia w celu poprawy komfortu przeglądania naszej witryny, aby wyświetlać spersonalizowane treści i ukierunkowane reklamy, analizować ruch w naszej witrynie, i zrozumieć, skąd pochodzą nasi goście.
Kontynuując, wyrażasz zgodę na korzystanie z plików cookie i innych technologii śledzenia oraz potwierdzasz, że masz co najmniej 16 lat lub zgodę rodzica lub opiekuna.