Mam klasę Java MyPojo
, którą chcę deserializować z formatu JSON. Skonfigurowałem specjalną klasę MixIn MyPojoDeMixIn
, aby pomóc mi w deserializacji. MyPojo
ma zmienne tylko int
i String
instancji połączone z odpowiednimi metodami pobierającymi i ustawiającymi. MyPojoDeMixIn
wygląda mniej więcej tak:
public abstract class MyPojoDeMixIn {
MyPojoDeMixIn(
@JsonProperty("JsonName1") int prop1,
@JsonProperty("JsonName2") int prop2,
@JsonProperty("JsonName3") String prop3) {}
}
W moim kliencie testowym wykonuję następujące czynności, ale oczywiście nie działa to w czasie kompilacji, ponieważ istnieje JsonMappingException
powiązanie z niezgodnością typów.
ObjectMapper m = new ObjectMapper();
m.getDeserializationConfig().addMixInAnnotations(MyPojo.class,MyPojoDeMixIn.class);
try { ArrayList<MyPojo> arrayOfPojo = m.readValue(response, MyPojo.class); }
catch (Exception e) { System.out.println(e) }
Zdaję sobie sprawę, że mógłbym rozwiązać ten problem, tworząc obiekt „Response”, który zawiera tylko element ArrayList<MyPojo>
, ale wtedy musiałbym utworzyć te nieco bezużyteczne obiekty dla każdego typu, który chcę zwrócić.
Spojrzałem również na JacksonInFiveMinutes w Internecie, ale miałem okropny czas, aby zrozumieć, o co chodzi Map<A,B>
i jaki ma to związek z moim problemem. Jeśli nie możesz powiedzieć, jestem całkowicie nowy w Javie i pochodzę z tła Obj-C. W szczególności wspominają o:
Oprócz tworzenia powiązań z obiektami POJO i typami „prostymi” istnieje jeszcze jeden wariant: powiązanie z kontenerami rodzajowymi (typowymi). Ten przypadek wymaga specjalnej obsługi ze względu na tak zwany typ wymazywania (używany przez Javę do implementacji typów generycznych w sposób nieco wstecznie zgodny), który uniemożliwia użycie czegoś takiego jak Collection.class (który nie kompiluje się).
Więc jeśli chcesz powiązać dane z mapą, będziesz musiał użyć:
Map<String,User> result = mapper.readValue(src, new TypeReference<Map<String,User>>() { });
Jak mogę deserializować bezpośrednio do ArrayList
?
Odpowiedzi:
Możesz deserializować bezpośrednio do listy przy użyciu
TypeReference
opakowania. Przykładowa metoda:public static <T> T fromJSON(final TypeReference<T> type, final String jsonPacket) { T data = null; try { data = new ObjectMapper().readValue(jsonPacket, type); } catch (Exception e) { // Handle the problem } return data; }
I jest używany w ten sposób:
final String json = ""; Set<POJO> properties = fromJSON(new TypeReference<Set<POJO>>() {}, json);
TypeReference Javadoc
źródło
TypeReference
- po prostu nie rozumiem, jak to zrobić ... Zobacz moją edycję powyżej, aby uzyskać instrukcje dotyczące używania typów ogólnych.arrayList.toString()
pliku about aNullPointerException
. Domyślam się, że może to być spowodowane tym, że myPOJO
nie dostosowuje się do odpowiednich konwencji nazewnictwa swoich właściwości, to znaczy cały problem polega na tym, że usługa internetowa zwraca,Prop1Member
a mój obiekt maProp1
. To jest jedyny prawdziwy powód, dla którego używam mixinów na początku, więc nie muszę umieszczać deklaracji@JsonProperty
w moich czystych obiektach.Innym sposobem jest użycie tablicy jako typu, np:
ObjectMapper objectMapper = new ObjectMapper(); MyPojo[] pojos = objectMapper.readValue(json, MyPojo[].class);
W ten sposób unikniesz wszystkich kłopotów z obiektem Type, a jeśli naprawdę potrzebujesz listy, zawsze możesz przekonwertować tablicę na listę przez:
IMHO to jest znacznie bardziej czytelne.
Aby była to rzeczywista lista (którą można modyfikować, zobacz ograniczenia
Arrays.asList()
), wykonaj następujące czynności:List<MyPojo> mcList = new ArrayList<>(Arrays.asList(pojos));
źródło
TypeFactory
opisanego w następnej odpowiedzi: stackoverflow.com/a/42458104/91497 jest sposobem Jacksona na określenie typu.Ten wariant wygląda na prostszy i bardziej elegancki.
źródło
CollectionType
odniesienie.Ja też mam ten sam problem. Mam plik json, który ma zostać przekonwertowany na ArrayList.
Konto wygląda tak.
Wszystkie powyższe klasy zostały odpowiednio opisane. Próbowałem TypeReference> () {}, ale nie działa.
Daje mi Arraylist, ale ArrayList ma link HashMap, który zawiera więcej połączonych hashmap zawierających ostateczne wartości.
Mój kod jest następujący:
public T unmarshal(String responseXML,String c) { ObjectMapper mapper = new ObjectMapper(); AnnotationIntrospector introspector = new JacksonAnnotationIntrospector(); mapper.getDeserializationConfig().withAnnotationIntrospector(introspector); mapper.getSerializationConfig().withAnnotationIntrospector(introspector); try { this.targetclass = (T) mapper.readValue(responseXML, new TypeReference<ArrayList<T>>() {}); } catch (JsonParseException e) { e.printStackTrace(); } catch (JsonMappingException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return this.targetclass; }
W końcu rozwiązałem problem. Jestem w stanie przekonwertować List w Json String bezpośrednio do ArrayList w następujący sposób:
JsonMarshallerUnmarshaller<T>{ T targetClass ; public ArrayList<T> unmarshal(String jsonString) { ObjectMapper mapper = new ObjectMapper(); AnnotationIntrospector introspector = new JacksonAnnotationIntrospector(); mapper.getDeserializationConfig().withAnnotationIntrospector(introspector); mapper.getSerializationConfig().withAnnotationIntrospector(introspector); JavaType type = mapper.getTypeFactory(). constructCollectionType(ArrayList.class, targetclass.getClass()) ; try { Class c1 = this.targetclass.getClass() ; Class c2 = this.targetclass1.getClass() ; ArrayList<T> temp = (ArrayList<T>) mapper.readValue(jsonString, type); return temp ; } catch (JsonParseException e) { e.printStackTrace(); } catch (JsonMappingException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return null ; } }
źródło
To działa dla mnie.
@Test public void cloneTest() { List<Part> parts = new ArrayList<Part>(); Part part1 = new Part(1); parts.add(part1); Part part2 = new Part(2); parts.add(part2); try { ObjectMapper objectMapper = new ObjectMapper(); String jsonStr = objectMapper.writeValueAsString(parts); List<Part> cloneParts = objectMapper.readValue(jsonStr, new TypeReference<ArrayList<Part>>() {}); } catch (Exception e) { //fail("failed."); e.printStackTrace(); } //TODO: Assert: compare both list values. }
źródło