web-dev-qa-db-ja.com

主要なラクダケースのWordの長さが1文字しかない場合、ジャクソン2が最初の大文字を認識しないのはなぜですか?

私は私のサービスにジャクソン2でSpring 4 MVCを使用しています。操作の1つについて、主要なラクダケースWordの属性を持つリクエストオブジェクトがあります。これは長さが1文字のみです。

private String aLogId;

このクラスには、適切な名前のゲッターとセッターがあります。

public String getALogId() { return aLogId; }
public void setALogId(String aLogId) { this.aLogId = aLogId; }

ただし、対応するJSONプロパティを使用してこのサービスにリクエストを投稿しようとすると:

{"aLogId":"This is a log id"}

フィールドが認識されず、コントローラークラスが呼び出されないという、Springフレームワークからの500応答を受信して​​います。

JSONを読み取れませんでした:認識されないフィールド「aLogId」(クラス

ただし、「L」を小文字に変更すると、要求は期待どおりにデシリアライズされ、コントローラークラスがヒットします。

{"alogId":"This is a log id"}

明らかにジャクソンは、属性のキャメルケース規則の2番目の単語であり、大文字にすることを意図しているのに、「L」が小文字であると予期するのはなぜですか。それは、最初のWordが1文字だけの長さだからですか?

リクエストオブジェクトには、最初のWordが複数の文字である他の属性があり、属性は、大文字と小文字が一致しないこの同じ問題に直面しません。

21
Hazok

私の理解では、JacksonはデフォルトでJava Beanの命名規則に非常に近いが厳密には同じではない独自の命名規則を使用します。MapperFeatureオプション、MapperFeature.USE_STD_BEAN_NAMING)が追加されましたJackson 2.5.0では、Java Bean命名規則を使用するようにJacksonに指示します- Jackson Issue 65 を参照してください。後方互換性のため、MapperFeature.USE_STD_BEAN_NAMINGのデフォルト値は偽。

3
Geoff Alexander

これは私のために働いています。ゲッターの@JsonPropertyアノテーション!

import com.fasterxml.jackson.annotation.JsonProperty;

public class PaytmRequestJson {
    private String ORDERID;
    private String MID;
    private String CHECKSUMHASH;

    @JsonProperty("ORDERID")
    public String getORDERID() {
        return ORDERID;
    }

    public void setORDERID(String ORDERID) {
        this.ORDERID = ORDERID;
    }

    @JsonProperty("MID")
    public String getMID() {
        return MID;
    }

    public void setMID(String MID) {
        this.MID = MID;
    }

    @JsonProperty("CHECKSUMHASH")
    public String getCHECKSUMHASH() {
        return CHECKSUMHASH;
    }

    public void setCHECKSUMHASH(String CHECKSUMHASH) {
        this.CHECKSUMHASH = CHECKSUMHASH;
    }
}
2
rupanjan

@JsonProperty現在の回答で示唆されているように、すべてのプロパティに対してそれを繰り返す必要があり、侵襲的であるという欠点があります(マッピングされているクラスを変更する必要があります)。

より一般的なアプローチは、カスタムプロパティ命名戦略を提供することです。

Java

public class CustomSnakeCase extends PropertyNamingStrategy.PropertyNamingStrategyBase {
    private static final Pattern REGEX = Pattern.compile("[A-Z]");

    @Override
    public String translate(String input) {
        if (input == null)
            return input; // garbage in, garbage out

        if (!input.isEmpty() && Character.isUpperCase(input.charAt(0)))
            input = input.substring(0, 1).toLowerCase() + input.substring(1);

        return REGEX.matcher(input).replaceAll("_$0").toLowerCase();
    }
}

Kotlin:

class CustomSnakeCase : PropertyNamingStrategy.PropertyNamingStrategyBase() {
    private companion object {
        val REGEX = Regex("[A-Z]")
    }

    override fun translate(input: String?) =
        input?.decapitalize()?.replace(REGEX, "_$0")?.toLowerCase()
}

使用法:

new ObjectMapper()
    .setPropertyNamingStrategy(new CustomSnakeCase())
    .enable(MapperFeature.USE_STD_BEAN_NAMING)

注:上記の実装では、入力がcamelCase(大文字ではない)であると想定しています。 USE_STD_BEAN_NAMINGは、aFieldなどの1文字のプレフィックスを一貫して処理するために必要です。

実装は次のマッピングを提供します。必要に応じて調整できます。

camelCase      snake_case
----------------------------
simple         simple
a              a
sepaRated      sepa_rated
iOException    i_o_exception
xOffset        x_offset
theWWW         the_w_w_w
sepaRated32    sepa_rated32
sepa32Rated    sepa32_rated
2
TheOperator