web-dev-qa-db-ja.com

LinkedHashMapを複雑なオブジェクトにキャストする

Jacksonを使用してDynamoDBにいくつかのデータを保存し、私の複雑なオブジェクトをJSONにマーシャリングするアプリケーションがあります。

たとえば、私がマーシャリングしているオブジェクトは次のようになります。

private String aString;
private List<SomeObject> someObjectList;

SomeObjectは次のようになります。

private int anInteger;
private SomeOtherObject;

someOtherObjectは次のようになります。

private long aLong;
private float aFloat; 

これは問題ありません。オブジェクトは問題なくマーシャリングされ、JSON文字列としてDBに保存されます。

DynamoDB Jacksonからデータを取得するときが来ると、Jacksonは自動的にJSONを取得し、それを元に戻します...「someObjectList」がList<LinkedHashMap>としてではなくList<SomeObject>!これはジャクソンの標準的な動作であり、これが起こっているという間違いではありません。

そのため、これは問題につながります。私のコードベースは、List<SomeObject>しかし、現実はList<LinkedHashMap>!私の質問は、LinkedHashMapを「SomeObject」に戻す方法です。明らかにこれは手動のプロセスですが、私が意味するのは、値を抽出することさえできないということです。

これを行う場合:

for (LinkedHashMap lhm : someObjectList) {
    // Convert the values back
}

SomeObjectListがLinkedHashMapではなく 'SomeObject'型であることを伝えるコンパイルエラーが表示されます。

これを行う場合:

for (SomeObject lhm : someObjectList) {
    // Convert the values back
}

LinkedHashMapを 'SomeObject'にキャストできないことを伝えるランタイムエラーが表示されます。

49
tarka

ObjectMapper.convertValue()は、値ごとに、またはリスト全体に対しても使用できます。ただし、変換するタイプを知る必要があります。

POJO pojo = mapper.convertValue(singleObject, POJO.class);
// or:
List<POJO> pojos = mapper.convertValue(listOfObjects, new TypeReference<List<POJO>>() { });

これは、機能的には次の場合と同じです。

byte[] json = mapper.writeValueAsBytes(singleObject);
POJO pojo = mapper.readValue(json, POJO.class);

ただし、中間ステップとしてメモリ内イベントシーケンスを使用する代わりに、データをJSONとして実際にシリアル化することは避けます。

120
StaxMan

この問題には良い解決策があります:

import com.fasterxml.jackson.databind.ObjectMapper;

ObjectMapper objectMapper = new ObjectMapper();

***DTO premierDriverInfoDTO = objectMapper.convertValue(jsonString, ***DTO.class); 

Map<String, String> map = objectMapper.convertValue(jsonString, Map.class);

なぜこの問題が発生したのですか?文字列をオブジェクトに変換するときに特定のタイプを指定しなかったと思います。オブジェクトは、User <T>などの汎用タイプを持つクラスです。

ObjectMapperの代わりにGsonを使用して、それを解決する別の方法があるかもしれません。 (またはこちらを参照してください GSONを使用したジェネリック型の逆シリアル化

Gson gson = new GsonBuilder().create();

Type type = new TypeToken<BaseResponseDTO<List<PaymentSummaryDTO>>>(){}.getType();

BaseResponseDTO<List<PaymentSummaryDTO>> results = gson.fromJson(jsonString, type);

BigDecimal revenue = results.getResult().get(0).getRevenue();
0
Donald Choi

値のリストを含むGenericResponseオブジェクトがあるという同様の問題がありました

 ResponseEntity<ResponseDTO> responseEntity = restTemplate.exchange(
                redisMatchedDriverUrl,
                HttpMethod.POST,
                requestEntity,
                ResponseDTO.class
        );

ObjectMapperの使用は、LinkedHashMapをそれぞれのDTOオブジェクトに変換するのに役立ちました

 ObjectMapper mapper = new ObjectMapper();

 List<DriverLocationDTO> driverlocationsList = mapper.convertValue(responseDTO.getData(), new TypeReference<List<DriverLocationDTO>>() { });
0
Aravind Rapuru