简体   繁体   中英

Using JsonAnySetter and JsonAnyGetter with ArrayList within Hashmap

So I'm trying to get my head around using Jackson Annotations, and i'm making requests against Riot's API. This is the response I'm getting: http://jsonblob.com/568079c8e4b01190df45d254 . Where the array after the summonerId (38584682) can be of a varying length.

The unique summoner ID will be different every single time too.

I want to map this response to a DTO.

For a similar situation with a different call I am doing:

@JsonIgnore
protected Map<String, SingleSummonerBasicDTO> nonMappedAttributes;

@JsonAnyGetter
public Map<String, SingleSummonerBasicDTO> getNonMappedAttributes() {
    return nonMappedAttributes;
}

@JsonAnySetter
public void setNonMappedAttributes(String key, SingleSummonerBasicDTO value) {
    if (nonMappedAttributes == null) {
        nonMappedAttributes = new HashMap<String, SingleSummonerBasicDTO>();
    }
    if (key != null) {
        if (value != null) {
            nonMappedAttributes.put(key, value);
        } else {
            nonMappedAttributes.remove(key);
        }
    }
}

From an answer on here. my thinking is to do a for-each loop for each of the elements in the array, but I don't know how to loop over something without having something to loop over.

I am completely stuck as to how the annotations work and how to proceed, any help if appreciated!

First of all, @JsonAnySetter was meant to deal with the case of varying properties, not for json arrays of varying length.

Jackson is quite capable of using Java Collections and Maps in serialization and deserialization. You just have to tell it the parameter type of the collection.

In your case, I have used a Map to capture the root element, making it the sole key with a List of DTOs as value. I use Jackson's type system ( TypeFactory and JavaType ) to tell jackson of all generic types.

This is the DTO that I have used:

public class SingleSummonerBasicDTO
{
    public String name;
    public String tier;
    public String queue;
    public List<SingleSummonerBasicDTOEntry> entries;

    @Override
    public String toString() {
        String toString = "\nSingleSummonerBasicDTO: " + name + " " + tier + " " + queue;
        for (SingleSummonerBasicDTOEntry entry : entries) {
            toString += "\n" + entry.toString();
        }
        return toString;
    }

    public static class SingleSummonerBasicDTOEntry
    {
        public String playerOrTeamId;
        public String playerOrTeamName;
        public String division;
        public int leaguePoints;
        public int wins;
        public int losses;
        public boolean isHotStreak;
        public boolean isVeteran;
        public boolean isFreshBlood;
        public boolean isInactive;

        @Override
        public String toString() {
            return "Entry: " + playerOrTeamId + " " + playerOrTeamName + " " + division + " " + leaguePoints + " " + wins + " " + 
                    losses + " " + isHotStreak + " " + isVeteran + " " + isInactive;
        }
    }

this is how to deserialise:

public static void main(String[] args)
{
    ObjectMapper mapper = new ObjectMapper();
    TypeFactory factory = mapper.getTypeFactory();
    // type of key of response map
    JavaType stringType = factory.constructType(String.class);
    // type of value of response map
    JavaType listOfDtosType = factory.constructCollectionLikeType(ArrayList.class, SingleSummonerBasicDTO.class);
    // create type of map
    JavaType responseType = factory.constructMapLikeType(HashMap.class, stringType, listOfDtosType);

    try (InputStream is = new FileInputStream("C://Temp/xx.json")) {
        Map<String, List<SingleSummonerBasicDTO>> response = new ObjectMapper().readValue(is, responseType);
        System.out.println(response);
    } catch (IOException e) {
        e.printStackTrace();
    }
}

output:

{38584682=[
SingleSummonerBasicDTO: Viktor's Masterminds PLATINUM RANKED_SOLO_5x5
Entry: 38584682 Lazrkiller V 64 291 295 false true false, 
SingleSummonerBasicDTO: Renekton's Horde SILVER RANKED_TEAM_5x5
Entry: TEAM-ff7d0db0-78ca-11e4-b402-c81f66dba0e7 Y U NO BABAR II 0 4 2 false false false, 
SingleSummonerBasicDTO: Pantheon's Chosen SILVER RANKED_TEAM_5x5
Entry: TEAM-d32018f0-d998-11e4-bfd2-c81f66dba0e7 Lose and Throw Away I 66 7 0 false false false, 
SingleSummonerBasicDTO: Jayce's Duelists SILVER RANKED_TEAM_5x5
Entry: TEAM-6c8fc440-a8ac-11e4-b65b-c81f66db920c TopBlokesNeverToke III 0 20 18 false false false]}

Here is the way how to parse your json:

Map<String, List<SingleSummonerBasicDTO>> summonersMap = new ObjectMapper()
    .readValue(json, new TypeReference<HashMap<String, List<SingleSummonerBasicDTO>>>() {});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM