java.lang.ClassCastException: java.util.LinkkedHashMap com.testing.models.Acount এ কাস্ট করা যাবে না


88

আমি ত্রুটির নীচে পাচ্ছি:

java.lang.ClassCastException: java.util.LinkedHashMap cannot be cast to com.testing.models.Account

নীচের কোড সহ

final int expectedId = 1;

Test newTest = create();

int expectedResponseCode = Response.SC_OK;

ArrayList<Account> account = given().when().expect().statusCode(expectedResponseCode)
    .get("accounts/" + newTest.id() + "/users")
    .as(ArrayList.class);
assertThat(account.get(0).getId()).isEqualTo(expectedId);

আমি না পারার কারণ আছে কি get(0)?


কাস্ট করা যাবে না কি ? বাকি ত্রুটি বার্তাটি কী?
অলিভার চার্লসওয়ার্থ

4
@ অলিভারচারসওয়ার্থও পুরো স্ট্যাকট্র্যাস যুক্ত করেছেন
প্যাশনেট ইঞ্জিনিয়ার

4
কি একটি Account? আপনি কেন একটি মানচিত্র থেকে এটিতে কাস্ট করার চেষ্টা করছেন?
ডেভ নিউটন

আমরা যারা গ্রন্থাগারের সাথে অপরিচিত হতে পারি তাদের জন্য আপনি কী বলতে পারেন যে এই given()পদ্ধতিটি স্ট্যাটিকভাবে কোন শ্রেণীর কাছ থেকে আমদানি করা হয়েছে?
মার্ক পিটারস 0

@ ডেভিনিউটন Accountহ'ল ড্রপউইজার্ডের একটি মডেল যা ব্যবহার করেcom.fasterxml.jackson.databind.annotations
প্যাশনেট ইঞ্জিনিয়ার

উত্তর:


112

বিষয়টি জ্যাকসন থেকে আসছে। কোন শ্রেণিতে ডিসিরিয়ালাইজ করা যায় সে সম্পর্কে যখন পর্যাপ্ত তথ্য না থাকে তখন এটি ব্যবহার করে LinkedHashMap

যেহেতু আপনি আপনার উপাদান ধরনের জ্যাকসন পরিচায়ক করছি না ArrayList, এটা কে না জানে যে আপনি একটি মধ্যে deserialize করতে চান ArrayListএর Accountগুলি। সুতরাং এটি ডিফল্ট ফিরে।

পরিবর্তে, আপনি সম্ভবত ব্যবহার করতে পারেন as(JsonNode.class), এবং তারপরে ObjectMapperবিশ্রাম-আশ্বাসের তুলনায় আরও উন্নততর পদ্ধতিতে ডিল করুন । এটার মতো কিছু:

ObjectMapper mapper = new ObjectMapper();

JsonNode accounts = given().when().expect().statusCode(expectedResponseCode)
    .get("accounts/" + newClub.getOwner().getCustId() + "/clubs")
    .as(JsonNode.class);


//Jackson's use of generics here are completely unsafe, but that's another issue
List<Account> accountList = mapper.convertValue(
    accounts, 
    new TypeReference<List<Account>>(){}
);

assertThat(accountList.get(0).getId()).isEqualTo(expectedId);

আপনি প্রতিক্রিয়াটিকে স্ট্রিং () হিসাবে সেটও করতে পারেন, অতিরিক্ত রূপান্তর করতে বাঁচান - রিডভ্যালু কোনও স্ট্রিংকে প্রথম আর্গ হিসাবে গ্রহণ করবে।
বিগডিউচ

@ বিগডিউচ: কেবল এটিকে পুনর্বিবেচনা করতে গিয়ে, যখন convertValueকোনও পদক্ষেপে এটি করতে পারে তখন আমাকে সেখানে টোকেনে রূপান্তরিত করার প্রয়োজন ছিল না । স্ট্রিং এ যাওয়াও কাজ করে।
মার্ক পিটার্স

45

নিম্নলিখিত চেষ্টা করুন:

POJO pojo = mapper.convertValue(singleObject, POJO.class);

বা:

List<POJO> pojos = mapper.convertValue(
    listOfObjects,
    new TypeReference<List<POJO>>() { });

আরও তথ্যের জন্য লিঙ্কডহ্যাশম্যাপ রূপান্তর দেখুন ।


4
"কনভার্টভ্যালু" দেখানোর জন্য +1। আমার একটি কেস ছিল যেখানে আমাকে তালিকা হিসাবে জেসন এর বাইরে একটি বিশেষ সম্পত্তি পড়ার দরকার ছিল এবং এটি আমার প্রয়োজন ঠিক।
গেমসলুটস

31

লিঙ্কডহ্যাশম্যাপ অবজেক্টস সংগ্রহের জন্য আমি JSON অ্যারেটিকে যেভাবে প্রশমিত করতে পারছিলাম তা হ'ল CollectionTypeএকটি ব্যবহার না করে TypeReference। এটিই আমি করেছি এবং কাজ করেছি :

public <T> List<T> jsonArrayToObjectList(String json, Class<T> tClass) throws IOException {
    ObjectMapper mapper = new ObjectMapper();
    CollectionType listType = mapper.getTypeFactory().constructCollectionType(ArrayList.class, tClass);
    List<T> ts = mapper.readValue(json, listType);
    LOGGER.debug("class name: {}", ts.get(0).getClass().getName());
    return ts;
}

ব্যবহার করে TypeReference, আমি এখনও লিংকডহ্যাশম্যাপস এর অ্যারেলিস্ট পেয়েছিলাম, কাজ করে না :

public <T> List<T> jsonArrayToObjectList(String json, Class<T> tClass) throws IOException {
    ObjectMapper mapper = new ObjectMapper();
    List<T> ts = mapper.readValue(json, new TypeReference<List<T>>(){});
    LOGGER.debug("class name: {}", ts.get(0).getClass().getName());
    return ts;
}

4
আমার সমস্যাও বাঁচিয়েছে। ধন্যবাদ!
ভ্লাদিমির গিলিভিচ

4
+1, আপনার ক্ষেত্রে পার্থক্যটি ছিল যে পদ্ধতিটি নিজেই জেনেরিক ছিল তাই Tটাইপটোকেনের মাধ্যমে পুনরায় সংশোধন করা যায় না, যা সাধারণত সহজ। ব্যক্তিগতভাবে আমি পেয়ারা এর সাহায্যকারী পছন্দ এটি এখনও typesafe এবং কোন ধারক টাইপ নির্দিষ্ট নয় কারণ: return new TypeToken<List<T>>(){}.where(new TypeParameter<T>(){}, tClass)। তবে জ্যাকসন TypeTokenতাই নেবেন না যাতে আপনার দরকার হয় .getType()
মার্ক পিটারগুলি

আমার সমস্যাও বাঁচিয়েছে। ধন্যবাদ!
শশাঙ্ক

ধন্যবাদ! এই ত্রুটিটি সমাধান করার জন্য অনেক সময় ব্যয় করেছি যতক্ষণ না আমি এই উত্তরটি পেয়েছি !!
glco

6

আমার একটি অনুরূপ ব্যতিক্রম ছিল (তবে ভিন্ন সমস্যা) - java.lang.ClassCastException: java.util.LinkedHashMap cannot be cast to org.bson.Documentএবং ভাগ্যক্রমে এটি সহজ সমাধান করা হয়েছে:

পরিবর্তে

List<Document> docs = obj.get("documents");
Document doc = docs.get(0)

যা দ্বিতীয় লাইনে ত্রুটি দেয়, একটি ব্যবহার করতে পারে

List<Document> docs = obj.get("documents");
Document doc = new Document(docs.get(0));

1

দুটি পদ্ধতির পার্স করে সমস্যা সমাধান করুন

  1. হুইট টাইপ একটি অবজেক্ট
public <T> T jsonToObject(String json, Class<T> type) {
        T target = null;
        try {
            target = objectMapper.readValue(json, type);
        } catch (Jsenter code hereonProcessingException e) {
            e.printStackTrace();
        }
    
        return target;
    }
  1. প্রকারের সাথে সংগ্রহের মোড়ক বস্তু object
public <T> T jsonToObject(String json, TypeReference<T> type) {
    T target = null;
    try {
        target = objectMapper.readValue(json, type);
    } catch (JsonProcessingException e) {
        e.printStackTrace();
    }
    return target;
}

0

এক্সএমএলকে deserialize এবং ধরণের রূপান্তর করার জন্য আমার এই পদ্ধতিটি রয়েছে:

public <T> Object deserialize(String xml, Class objClass ,TypeReference<T> typeReference ) throws IOException {
    XmlMapper xmlMapper = new XmlMapper();
    Object obj = xmlMapper.readValue(xml,objClass);
    return  xmlMapper.convertValue(obj,typeReference );   
}

এবং এই কল:

List<POJO> pojos = (List<POJO>) MyUtilClass.deserialize(xml, ArrayList.class,new TypeReference< List< POJO >>(){ });

0

আপনি যখন জ্যাকসনটি স্ট্রিং থেকে আপনার কংক্রিট শ্রেণিতে মানচিত্রের জন্য ব্যবহার করেন, বিশেষত যদি আপনি জেনেরিক ধরণের সাথে কাজ করেন। তাহলে এই সমস্যাটি বিভিন্ন শ্রেণীর লোডার কারণে ঘটতে পারে। নীচের দৃশ্যের সাথে আমি এটি একবারে পূরণ করেছি:

প্রকল্প বি লাইব্রেরি এ এর ​​উপর নির্ভর করে

গ্রন্থাগার এ:

public class DocSearchResponse<T> {
 private T data;
}

এটিতে বাহ্যিক উত্স থেকে ডেটা জিজ্ঞাসা করার পরিষেবা রয়েছে এবং কংক্রিট শ্রেণিতে রূপান্তর করতে জ্যাকসন ব্যবহার করুন

public class ServiceA<T>{
  @Autowired
  private ObjectMapper mapper;
  @Autowired
  private ClientDocSearch searchClient;

  public DocSearchResponse<T> query(Criteria criteria){
      String resultInString = searchClient.search(criteria);
      return convertJson(resultInString)
  }
}

public DocSearchResponse<T> convertJson(String result){
     return mapper.readValue(result, new TypeReference<DocSearchResponse<T>>() {});
  }
}

প্রকল্প বিতে:

public class Account{
 private String name;
 //come with other attributes
}

এবং আমি জিজ্ঞাসা তৈরি করতে এবং পাশাপাশি ডেটা রূপান্তর করতে লাইব্রেরি থেকে পরিষেবাএ ব্যবহার করি

public class ServiceAImpl extends ServiceA<Account> {
    
}

এবং এটি ব্যবহার করুন

public class MakingAccountService {
    @Autowired
    private ServiceA service;
    public void execute(Criteria criteria){
      
        DocSearchResponse<Account> result = service.query(criteria);
        Account acc = result.getData(); //  java.util.LinkedHashMap cannot be cast to com.testing.models.Account
    }
}

এটি ঘটেছিল কারণ লাইব্রেরিএর ক্লাস লোডার থেকে, জ্যাকসন অ্যাকাউন্ট ক্লাসটি লোড করতে পারে না, তারপরে জ্যাকসনকে convertJsonতার কাজটি করার জন্য প্রজেক্ট বি তে কেবল ওভাররাইড পদ্ধতি

public class ServiceAImpl extends ServiceA<Account> {
        @Override
        public DocSearchResponse<T> convertJson(String result){
         return mapper.readValue(result, new TypeReference<DocSearchResponse<T>>() {});
      }
    }
 }
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.