簡體   English   中英

奇怪的 jackson ObjectMapper 行為

[英]Strange jackson ObjectMapper behavior

我的 Java 應用程序接收 Spotify API 授權令牌並將它們映射到 Jackson 的 POJO 時遇到問題。

每次我的應用程序從 Spotify API 請求數據時,我都會從這個鏈接獲取一個新的訪問令牌: https://accounts.spotify.com/api/token?grant_type=client_credentials

答案是 JSON,看起來像這樣:

{
    "access_token":"BQAJmzZOdh2egvWEOEwy4wv-VKdhTUc4eZYJrIfAibjWLR4MPfrbV6KBNIiomPwJKsQN-3vmrGmG7lOXFaI",
    "token_type":"Bearer",
    "expires_in":3600,
    "scope":""
}

每次我啟動我的應用程序時,第一次運行良好,但隨后崩潰:

Exception in thread "main" com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance of `com.slowedandthrowed.darkjazzbot.mapping.spotify.TokenRequest` (although at least 
one Creator exists): no String-argument constructor/factory method to deserialize from String value ('BQCcDMOKUiVPscDrrBH77b2QbN9FuqjAJHuM3_1QD39MO9L20XzXneZUlJeIyukBVhPpaCWnKWRjUdggaCM') at [Source: (String)"{"access_token":"BQCcDMOKUiVPscDrrBH77b2QbN9FuqjAJHuM3_1QD39MO9L20XzXneZUlJeIyukBVhPpaCWnKWRjUdggaCM","token_type":"Bearer","expires_in":3600,"scope":""}"; line: 1, column: 17]

每次我需要 map 訪問令牌 JSON 到 POJO 時,我通過創建一個新的 ObjectMapper 來解決這個問題,但如果它是一個生產應用程序,它會損害性能,所以我需要找出使用一個的問題是什么一直是 ObjectMapper 實例。

我還嘗試將 map 這個 JSON 映射到 Map<String,String> 而不是將其映射到TokenRequest.class結果是一樣的,所以我認為這不是映射失敗的原因。

private String requestAccessToken() throws IOException {
        TokenRequest tokenRequest = null;
        
        URL accessTokenUrl = new URL(SPOTIFY_TOKEN_LINK);
        
        HttpURLConnection tokenConnection = (HttpURLConnection) accessTokenUrl.openConnection();
        tokenConnection.setRequestProperty("Authorization", authString);
        tokenConnection.setDoOutput(true);
        tokenConnection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
        
        tokenConnection.setRequestMethod("POST");
        
        OutputStreamWriter wr = new OutputStreamWriter(tokenConnection.getOutputStream());
        wr.write(TOKEN_REQUEST_PARAMETERS);
        wr.flush();
        
        System.out.println("Wow! Posted!");
        
        InputStream inputStream = tokenConnection.getInputStream();
        BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));

        
        StringBuilder inputBuilder = new StringBuilder();
        String input = null;
        
        while ((input = reader.readLine()) != null) inputBuilder.append(input);
        
        
        System.out.println("================================= TOKEN INPUT ======================================");
        System.out.println(inputBuilder.toString());
        System.out.println("================================= TOKEN INPUT ======================================");

        
        tokenRequest = spotifyObjectMapper.readValue(inputBuilder.toString(), TokenRequest.class);
        

        inputStream.close();
        reader.close();
        tokenConnection.disconnect();
        
        return tokenRequest.getAccessToken();
    }

令牌請求.java:

package com.slowedandthrowed.darkjazzbot.mapping.spotify;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
import com.fasterxml.jackson.annotation.JsonRootName;

@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonPropertyOrder({
        "access_token",
        "token_type",
        "expires_in",
        "scope"
})
@JsonRootName("access_token")
public class TokenRequest {

    @JsonProperty("access_token")
    private String accessToken;
    @JsonProperty("token_type")
    private String tokenType;
    @JsonProperty("expires_in")
    private Long expiresIn;
    @JsonProperty("scope")
    private String scope;

    @JsonProperty("access_token")
    public String getAccessToken() {
        return accessToken;
    }

    @JsonProperty("access_token")
    public void setAccessToken(String accessToken) {
        this.accessToken = accessToken;
    }

    @JsonProperty("token_type")
    public String getTokenType() {
        return tokenType;
    }

    @JsonProperty("token_type")
    public void setTokenType(String tokenType) {
        this.tokenType = tokenType;
    }

    @JsonProperty("expires_in")
    public Long getExpiresIn() {
        return expiresIn;
    }

    @JsonProperty("expires_in")
    public void setExpiresIn(Long expiresIn) {
        this.expiresIn = expiresIn;
    }

    @JsonProperty("scope")
    public String getScope() {
        return scope;
    }

    @JsonProperty("scope")
    public void setScope(String scope) {
        this.scope = scope;
    }
}

我修復了我的程序,因為我為自己制造了問題。 我通過不同的 API 接收到不同的數據,並通過 Jackson ObjectMapper 的單個實例將其映射到 POJO。 一些JSON object自己包含數據:

{
"property1":value1,
"property2":value2
}

而其他人有單個嵌套的 object,其中包含數據:

{
"object":{"property1":value1,
"property2":value2
}}

所以我決定將 UNWRAP_ROOT_VALUE 變為 TRUE,然后我的 object 映射器更改了它的 state,因此它的行為在我第一次和第二次嘗試接收訪問令牌時變得不同。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM