অবজেক্টম্যাপার ব্যবহার করে কীভাবে ডিফল্ট কনস্ট্রাক্টর ছাড়াই অপরিবর্তনীয় কোনও অবজেক্টকে ডি / সিরিয়ালাইজ করা যায়?


106

আমি com.fasterxml.jackson.databind.ObjectMapper ব্যবহার করে একটি অপরিবর্তনীয় অবজেক্টটি সিরিয়ালাইজ করতে এবং ডিজিটালাইজ করতে চাই।

অপরিবর্তনীয় বর্গটি দেখতে দেখতে (কেবলমাত্র 3 টি অভ্যন্তরীণ গুণাবলী, গিটার এবং নির্মাণকারী):

public final class ImportResultItemImpl implements ImportResultItem {

    private final ImportResultItemType resultType;

    private final String message;

    private final String name;

    public ImportResultItemImpl(String name, ImportResultItemType resultType, String message) {
        super();
        this.resultType = resultType;
        this.message = message;
        this.name = name;
    }

    public ImportResultItemImpl(String name, ImportResultItemType resultType) {
        super();
        this.resultType = resultType;
        this.name = name;
        this.message = null;
    }

    @Override
    public ImportResultItemType getResultType() {
        return this.resultType;
    }

    @Override
    public String getMessage() {
        return this.message;
    }

    @Override
    public String getName() {
        return this.name;
    }
}

তবে আমি যখন এই ইউনিট পরীক্ষা চালাচ্ছি:

@Test
public void testObjectMapper() throws Exception {
    ImportResultItemImpl originalItem = new ImportResultItemImpl("Name1", ImportResultItemType.SUCCESS);
    String serialized = new ObjectMapper().writeValueAsString((ImportResultItemImpl) originalItem);
    System.out.println("serialized: " + serialized);

    //this line will throw exception
    ImportResultItemImpl deserialized = new ObjectMapper().readValue(serialized, ImportResultItemImpl.class);
}

আমি এই ব্যতিক্রম পাই:

com.fasterxml.jackson.databind.JsonMappingException: No suitable constructor found for type [simple type, class eu.ibacz.pdkd.core.service.importcommon.ImportResultItemImpl]: can not instantiate from JSON object (missing default constructor or creator, or perhaps need to add/enable type information?)
 at [Source: {"resultType":"SUCCESS","message":null,"name":"Name1"}; line: 1, column: 2]
    at 
... nothing interesting here

এই ব্যতিক্রমটি আমাকে একটি ডিফল্ট কনস্ট্রাক্টর তৈরি করতে বলে, তবে এটি একটি পরিবর্তনযোগ্য অবজেক্ট, তাই আমি এটি রাখতে চাই না। এটি কীভাবে অভ্যন্তরীণ বৈশিষ্ট্যগুলি সেট করবে? এটি সম্পূর্ণরূপে এপিআই এর ব্যবহারকারীকে বিভ্রান্ত করবে।

সুতরাং আমার প্রশ্নটি: আমি কি কোনওরকমভাবে ডিফল্ট নির্মাতা ছাড়াই অপরিবর্তনীয় বস্তুগুলিকে ডি / সিরিয়ালাইজ করতে পারি?


নির্ণয় করার সময়, ডিজায়ালাইজারটি আপনার কোনও নির্মাণকারীর সম্পর্কে জানেন না, তাই এটি ডিফল্ট কনস্ট্রাক্টরকে আঘাত করে। এই কারণে আপনাকে একটি ডিফল্ট নির্মাতা তৈরি করতে হবে, যা অপরিবর্তনীয়তা পরিবর্তন করবে না। এছাড়াও আমি দেখছি ক্লাস চূড়ান্ত নয়, কেন? কারও কার্যকারিতা ওভাররাইড করতে পারে তাই না?
অভিনববা বসু

ক্লাস চূড়ান্ত নয়, কারণ আমি এটি লিখতে ভুলে গেছি, দেখার জন্য আপনাকে ধন্যবাদ :)
মিশাল

উত্তর:


149

জ্যাকসনকে কীভাবে ডিসরিয়ালাইজেশনের জন্য কোনও অবজেক্ট তৈরি করবেন তা জানাতে, আপনার নির্মাতাদের জন্য এটি @JsonCreatorএবং @JsonPropertyটীকাগুলি ব্যবহার করুন:

@JsonCreator
public ImportResultItemImpl(@JsonProperty("name") String name, 
        @JsonProperty("resultType") ImportResultItemType resultType, 
        @JsonProperty("message") String message) {
    super();
    this.resultType = resultType;
    this.message = message;
    this.name = name;
}

1
+1 ধন্যবাদ সের্গে। এটি কাজ করেছে .. তবে জসনক্রিটার টীকাটি ব্যবহার করার পরেও আমার সমস্যা হয়েছিল .. তবে কিছু পর্যালোচনা করার পরে আমি বুঝতে পারি যে আমি আমার সংস্থানটিতে অনুরোধবডি টীকাটি ব্যবহার করতে ভুলে গেছি। এখন এটি কাজ করে .. থ্যাঙ্কস আবার।
রাহুল

4
আপনি যদি কোনও ডিফল্ট কনস্ট্রাক্টর যোগ করতে না পারেন, বা এরপরে @JsonCreatorএবং @JsonPropertyটীকাগুলি আপনার POJO এ পরিবর্তন করার অ্যাক্সেস না পাওয়ায়? এখনও কি অবজেক্টটিকে ডিসেরায়াল করার কোনও উপায় আছে?
জ্যাক স্ট্র

1
@ জ্যাকস্ট্রাও ১) অবজেক্ট থেকে সাবক্লাস করুন এবং সমস্ত গেটার এবং সেটারকে ওভাররাইড করুন। ২) ক্লাসের জন্য আপনার নিজস্ব সিরিয়ালাইজার / ডিসরিযালাইজার লিখুন এবং এটি ব্যবহার করুন ("কাস্টম সিরিয়ালাইজার" অনুসন্ধান করুন 3) অবজেক্টটি মোড়ানো এবং কেবলমাত্র একটি সম্পত্তির জন্য একটি সিরিয়ালাইজার / ডিজিজারাইজার লিখুন (এটি আপনাকে সিরিয়াল লেখার চেয়ে কম কাজ করতে দেয়) ক্লাস নিজেই, কিন্তু নাও হতে পারে)।
এরিক

আপনার মন্তব্য +1 আমাকে বাঁচাতে! আমি যে সন্ধান
পেয়েছি

34

আপনি একটি বেসরকারী ডিফল্ট নির্মাতা ব্যবহার করতে পারেন, জ্যাকসন তারপরে ক্ষেত্রগুলি ব্যক্তিগত চূড়ান্ত হলেও প্রতিচ্ছবিটির মাধ্যমে পূরণ করবেন।

সম্পাদনা: এবং যদি আপনার উত্তরাধিকার থাকে তবে অভিভাবক শ্রেণীর জন্য একটি সুরক্ষিত / প্যাকেজ-সুরক্ষিত ডিফল্ট কনস্ট্রাক্টর ব্যবহার করুন।


কেবলমাত্র এই উত্তরের উপর ভিত্তি করে, আপনি ডিগ্রিওলাইজ করতে চান এমন ক্লাসটি যদি অন্য শ্রেণি প্রসারিত করে তবে আপনি সুপার বর্গের ডিফল্ট নির্মাতা (বা উভয় শ্রেণি) সুরক্ষিত করতে পারেন।
KWILLIAMS

3

সের্গেই পেটুনিনের প্রথম উত্তরটি সঠিক। তবে আমরা কনস্ট্রাক্টরের প্রতিটি প্যারামিটারে রিডানডেন্ট @ জসনপ্রপার্টি টীকা মুছে ফেলার সাথে কোডটি সহজ করতে পারি।

এটি com.fasterxml.jackson.module.paramnames.ParameterNamesModule অবজেক্টম্যাপারে যুক্ত করার মাধ্যমে করা যেতে পারে:

new ObjectMapper()
        .registerModule(new ParameterNamesModule(JsonCreator.Mode.PROPERTIES))

(বিটিডব্লিউ: এই মডিউলটি স্প্রিংবুটে ডিফল্টরূপে নিবন্ধভুক্ত।

উদাহরণ স্বরূপ:

public class FieldValidationError {
  private final String field;
  private final String error;

  @JsonCreator
  public FieldValidationError(String field,
                              String error) {
    this.field = field;
    this.error = error;
  }

  public String getField() {
    return field;
  }

  public String getError() {
    return error;
  }
}

এবং অবজেক্টম্যাপার কোনও ত্রুটি ছাড়াই এই জসনকে ডিসিজায়ালাইজ করেছে:

{
  "field": "email",
  "error": "some text"
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.