আমি জ্যাকসনের সাথে কাস্টম সিরিয়ালাইজার কীভাবে ব্যবহার করব?


111

আমার দুটি জাভা ক্লাস রয়েছে যা আমি জ্যাকসন ব্যবহার করে জেএসএনে সিরিয়াল করতে চাই:

public class User {
    public final int id;
    public final String name;

    public User(int id, String name) {
        this.id = id;
        this.name = name;
    }
}

public class Item {
    public final int id;
    public final String itemNr;
    public final User createdBy;

    public Item(int id, String itemNr, User createdBy) {
        this.id = id;
        this.itemNr = itemNr;
        this.createdBy = createdBy;
    }
}

আমি এই JSON এ একটি আইটেম সিরিয়ালাইজ করতে চাই:

{"id":7, "itemNr":"TEST", "createdBy":3}

ব্যবহারকারী সিরিয়ালযুক্ত শুধুমাত্র অন্তর্ভুক্ত করতে id। আমি JSON- তে সমস্ত ব্যবহারকারীর বস্তুগুলি সিরিলাইজ করতে সক্ষম হব:

{"id":3, "name": "Jonas", "email": "jonas@example.com"}

সুতরাং আমি অনুমান করি যে এর জন্য আমাকে একটি কাস্টম সিরিয়ালাইজার লিখতে হবে Itemএবং এটি দিয়ে চেষ্টা করতে হবে:

public class ItemSerializer extends JsonSerializer<Item> {

@Override
public void serialize(Item value, JsonGenerator jgen,
        SerializerProvider provider) throws IOException,
        JsonProcessingException {
    jgen.writeStartObject();
    jgen.writeNumberField("id", value.id);
    jgen.writeNumberField("itemNr", value.itemNr);
    jgen.writeNumberField("createdBy", value.user.id);
    jgen.writeEndObject();
}

}

আমি জ্যাকসন থেকে এই কোডটি দিয়ে জেএসনকে সিরিয়ালাইজ করি কীভাবে: কাস্টম সিরিয়ালাইজার্স :

ObjectMapper mapper = new ObjectMapper();
SimpleModule simpleModule = new SimpleModule("SimpleModule", 
                                              new Version(1,0,0,null));
simpleModule.addSerializer(new ItemSerializer());
mapper.registerModule(simpleModule);
StringWriter writer = new StringWriter();
try {
    mapper.writeValue(writer, myItem);
} catch (JsonGenerationException e) {
    e.printStackTrace();
} catch (JsonMappingException e) {
    e.printStackTrace();
} catch (IOException e) {
    e.printStackTrace();
}

তবে আমি এই ত্রুটিটি পেয়েছি:

Exception in thread "main" java.lang.IllegalArgumentException: JsonSerializer of type com.example.ItemSerializer does not define valid handledType() (use alternative registration method?)
    at org.codehaus.jackson.map.module.SimpleSerializers.addSerializer(SimpleSerializers.java:62)
    at org.codehaus.jackson.map.module.SimpleModule.addSerializer(SimpleModule.java:54)
    at com.example.JsonTest.main(JsonTest.java:54)

আমি জ্যাকসনের সাথে কীভাবে কাস্টম সিরিয়াল ব্যবহার করতে পারি?


এইভাবে আমি গসন দিয়ে এটি করব:

public class UserAdapter implements JsonSerializer<User> {

    @Override 
    public JsonElement serialize(User src, java.lang.reflect.Type typeOfSrc,
            JsonSerializationContext context) {
        return new JsonPrimitive(src.id);
    }
}

    GsonBuilder builder = new GsonBuilder();
    builder.registerTypeAdapter(User.class, new UserAdapter());
    Gson gson = builder.create();
    String json = gson.toJson(myItem);
    System.out.println("JSON: "+json);

তবে এখনই জ্যাকসনের সাথে আমার এটি করা দরকার, যেহেতু গসনের ইন্টারফেসের জন্য সমর্থন নেই।


আপনি কীভাবে / কোথায় জ্যাকসনকে আপনার কাস্টম সিরিয়ালাইজারটি ব্যবহার করতে পেলেন Item? আমার একটি সমস্যা হচ্ছে যেখানে আমার নিয়ামক পদ্ধতিটি একটি স্ট্যান্ডার্ড সিরিয়ালযুক্ত বস্তুটি ফেরত দেয় TypeA, তবে অন্য একটি নির্দিষ্ট নিয়ামক পদ্ধতির জন্য, আমি এটিকে আলাদাভাবে সিরিয়ালাইজ করতে চাই। দেখতে কেমন লাগবে?
ডন চ্যাডেল

আমি জ্যাকসনের সাথে কাস্টম সিরিয়ালাইজার কীভাবে লিখব সে সম্পর্কে একটি পোস্ট লিখেছিলাম যা কারওর পক্ষে সহায়ক হতে পারে।
স্যাম বেরি

উত্তর:


51

যেমনটি উল্লেখ করা হয়েছে, @ জসনভ্যালু একটি ভাল উপায়। তবে যদি আপনি কোনও কাস্টম সিরিয়ালাইজকে আপত্তি করেন না তবে আইটেমের জন্য একটি লিখতে হবে না তবে ব্যবহারকারীর জন্য একটি লিখতে হবে - যদি তা হয় তবে এটি এতটা সহজ হবে:

public void serialize(Item value, JsonGenerator jgen,
    SerializerProvider provider) throws IOException,
    JsonProcessingException {
  jgen.writeNumber(id);
}

তবুও আরেকটি সম্ভাবনা বাস্তবায়ন করা JsonSerializable, এক্ষেত্রে কোনও নিবন্ধকরণের প্রয়োজন নেই।

ত্রুটি হিসাবে; এটি অদ্ভুত - আপনি সম্ভবত পরবর্তী সংস্করণে আপগ্রেড করতে চান। তবে এটি প্রসারিত org.codehaus.jackson.map.ser.SerializerBaseকরা আরও নিরাপদ কারণ এটিতে অ-প্রয়োজনীয় পদ্ধতির মানক প্রয়োগ (যেমন প্রকৃত সিরিয়ালাইজেশন কল ছাড়া সমস্ত কিছুই) থাকবে।


এটির সাথে আমি একই ত্রুটি পেয়েছি:Exception in thread "main" java.lang.IllegalArgumentException: JsonSerializer of type com.example.JsonTest$UserSerilizer does not define valid handledType() (use alternative registration method?) at org.codehaus.jackson.map.module.SimpleSerializers.addSerializer(SimpleSerializers.java:62) at org.codehaus.jackson.map.module.SimpleModule.addSerializer(SimpleModule.java:54) at com.example.JsonTest.<init>(JsonTest.java:27) at com.exampple.JsonTest.main(JsonTest.java:102)
জোনাস

আমি জ্যাকসনের সর্বশেষতম স্থিতিশীল সংস্করণ, 1.8.5 ব্যবহার করি।
জোনাস

4
ধন্যবাদ। আমি একবার তাকান ... আহ! এটি আসলে সহজ (ত্রুটির বার্তাটি ভাল না হলেও) - আপনাকে কেবল সিরিয়ালাইজারের জন্য শ্রেণি নির্দিষ্ট করার জন্য বিভিন্ন পদ্ধতিতে সিরিয়ালাইজারটি নিবন্ধিত করতে হবে: যদি তা না হয় তবে এটি অবশ্যই হ্যান্ডল্ড টাইপ () থেকে শ্রেণি ফিরে আসতে পারে। সুতরাং জাভাটাইপ বা ক্লাসকে যুক্তি হিসাবে গ্রহণ করে এমন 'অ্যাডসারিয়ালাইজার' ব্যবহার করুন এবং এটি কাজ করা উচিত।
স্ট্যাকসমান

যদি এই চালানো হচ্ছে না?
মতেজ জে

62

আপনি লাগাতে পারেন @JsonSerialize(using = CustomDateSerializer.class)বস্তুর কোনো তারিখ ক্ষেত্রের উপর ধারাবাহিকভাবে করতে হবে।

public class CustomDateSerializer extends SerializerBase<Date> {

    public CustomDateSerializer() {
        super(Date.class, true);
    }

    @Override
    public void serialize(Date value, JsonGenerator jgen, SerializerProvider provider)
        throws IOException, JsonProcessingException {
        SimpleDateFormat formatter = new SimpleDateFormat("EEE MMM dd yyyy HH:mm:ss 'GMT'ZZZ (z)");
        String format = formatter.format(value);
        jgen.writeString(format);
    }

}

1
লক্ষণীয়: @JsonSerialize(contentUsing= ...)সংগ্রহগুলি টীকা দেওয়ার সময় ব্যবহার করুন (উদাঃ @JsonSerialize(contentUsing= CustomDateSerializer.class) List<Date> dates)
কোডরেচেট

33

আমি এটি করার চেষ্টাও করেছি, এবং জ্যাকসনের ওয়েব পৃষ্ঠায় উদাহরণ কোডে একটি ভুল রয়েছে .classযা কল টু addSerializer()পদ্ধতিতে টাইপ ( ) অন্তর্ভুক্ত করতে ব্যর্থ হয়েছে , যা এইভাবে পড়তে হবে:

simpleModule.addSerializer(Item.class, new ItemSerializer());

অন্য কথায়, এগুলি সেই লাইনগুলি যা তাত্ক্ষণিকভাবে simpleModuleএবং সিরিয়ালাইজার যুক্ত করে (পূর্ববর্তী ভুল লাইনের সাথে মন্তব্য করেছে):

ObjectMapper mapper = new ObjectMapper();
SimpleModule simpleModule = new SimpleModule("SimpleModule", 
                                          new Version(1,0,0,null));
// simpleModule.addSerializer(new ItemSerializer());
simpleModule.addSerializer(Item.class, new ItemSerializer());
mapper.registerModule(simpleModule);

এফওয়াইআই: সঠিক উদাহরণ কোডের জন্য এখানে রেফারেন্স দেওয়া হয়েছে: http://wiki.fasterxml.com/ jacksonFeatureModules


9

@ জসনভ্যালু ব্যবহার করুন:

public class User {
    int id;
    String name;

    @JsonValue
    public int getId() {
        return id;
    }
}

@ জসনভ্যালু কেবলমাত্র পদ্ধতিতে কাজ করে তাই আপনাকে অবশ্যই getId পদ্ধতি যুক্ত করতে হবে। আপনার কাস্টম সিরিয়ালাইজারটি পুরোপুরি এড়িয়ে যেতে সক্ষম হওয়া উচিত।


2
আমি মনে করি এটি কোনও ব্যবহারকারীর সিরিয়ালিয়াল করার সমস্ত প্রয়াসকে প্রভাবিত করবে, যার ফলে জেএসএনের মাধ্যমে কোনও ব্যবহারকারীর নাম প্রকাশ করতে কখনও অসুবিধা হয়।
পল এম

আমি এই সমাধানটি ব্যবহার করতে পারি না, কারণ আমার সমস্ত ক্ষেত্রের সাথে সমস্ত ব্যবহারকারীর অবজেক্টকে সিরিয়ালাইজ করতে সক্ষম হওয়া প্রয়োজন। এবং এই সমাধানটি সেই সিরিয়ালটিকে ভঙ্গ করবে যেহেতু কেবল আইডি-ফিল্ড অন্তর্ভুক্ত করা হবে। জ্যাকসনের মতো কাস্টম সেরিলাইজার তৈরি করার কোনও উপায় কি এটি গসনের মতো নয়?
জোনাস

1
আপনি কীভাবে মন্তব্য করতে পারেন যে জেএসএন ভিউ (আমার উত্তরে) আপনার প্রয়োজনীয়তার সাথে মেলে না কেন?
পল এম

@ ব্যবহারকারী: এটি একটি ভাল সমাধান হতে পারে, আমি এটি সম্পর্কে পড়ছি এবং চেষ্টা করছি।
জোনাস

2
নোট, এছাড়াও, আপনি আপনার সম্পত্তি (ক্ষেত্র বা গেটর) এর জন্য নির্দিষ্ট সিরিয়ালাইজেশন নির্দেশ করতে @ জসনসিরাইলেস (= মাইআরিশায়ালার.ক্লাস ব্যবহার করে) ব্যবহার করতে পারেন, সুতরাং এটি কেবল সদস্য সম্পত্তি হিসাবে ব্যবহৃত হয় এবং সমস্ত ধরণের উদাহরণ নয়।
স্টেক্সম্যান 24

8

আমি একটি রীতিন্যের জন্য একটি উদাহরণ লিখেছি Timestamp.class সিরিয়ালাইজেশন / deserialization , আপনি যা চান তা আপনি এটি ব্যবহার করতে পারেন।

অবজেক্ট ম্যাপার তৈরি করার সময় এই জাতীয় কিছু করুন:

public class JsonUtils {

    public static ObjectMapper objectMapper = null;

    static {
        objectMapper = new ObjectMapper();
        SimpleModule s = new SimpleModule();
        s.addSerializer(Timestamp.class, new TimestampSerializerTypeHandler());
        s.addDeserializer(Timestamp.class, new TimestampDeserializerTypeHandler());
        objectMapper.registerModule(s);
    };
}

উদাহরণস্বরূপ java eeআপনি এটি দিয়ে এটি সূচনা করতে পারেন:

import java.time.LocalDateTime;

import javax.ws.rs.ext.ContextResolver;
import javax.ws.rs.ext.Provider;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;

@Provider
public class JacksonConfig implements ContextResolver<ObjectMapper> {

    private final ObjectMapper objectMapper;

    public JacksonConfig() {
        objectMapper = new ObjectMapper();
        SimpleModule s = new SimpleModule();
        s.addSerializer(Timestamp.class, new TimestampSerializerTypeHandler());
        s.addDeserializer(Timestamp.class, new TimestampDeserializerTypeHandler());
        objectMapper.registerModule(s);
    };

    @Override
    public ObjectMapper getContext(Class<?> type) {
        return objectMapper;
    }
}

যেখানে সিরিয়ালাইজারটি এমন কিছু হওয়া উচিত:

import java.io.IOException;
import java.sql.Timestamp;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;

public class TimestampSerializerTypeHandler extends JsonSerializer<Timestamp> {

    @Override
    public void serialize(Timestamp value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException {
        String stringValue = value.toString();
        if(stringValue != null && !stringValue.isEmpty() && !stringValue.equals("null")) {
            jgen.writeString(stringValue);
        } else {
            jgen.writeNull();
        }
    }

    @Override
    public Class<Timestamp> handledType() {
        return Timestamp.class;
    }
}

এবং deserializer এর মতো কিছু:

import java.io.IOException;
import java.sql.Timestamp;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.SerializerProvider;

public class TimestampDeserializerTypeHandler extends JsonDeserializer<Timestamp> {

    @Override
    public Timestamp deserialize(JsonParser jp, DeserializationContext ds) throws IOException, JsonProcessingException {
        SqlTimestampConverter s = new SqlTimestampConverter();
        String value = jp.getValueAsString();
        if(value != null && !value.isEmpty() && !value.equals("null"))
            return (Timestamp) s.convert(Timestamp.class, value);
        return null;
    }

    @Override
    public Class<Timestamp> handledType() {
        return Timestamp.class;
    }
}

7

এটি হ'ল জ্যাকসন সিরিয়ালাইজেশন বোঝার চেষ্টা করার সময় আমি সেই আচরণের নিদর্শনগুলি লক্ষ্য করেছি।

1) ধরে নিন সেখানে একটি ক্লাসরুম এবং একটি শ্রেণির ছাত্র রয়েছে। আমি সবকিছুকে স্বাচ্ছন্দ্যের জন্য সর্বজনীন এবং চূড়ান্ত করে তুলেছি।

public class Classroom {
    public final double double1 = 1234.5678;
    public final Double Double1 = 91011.1213;
    public final Student student1 = new Student();
}

public class Student {
    public final double double2 = 1920.2122;
    public final Double Double2 = 2324.2526;
}

2) ধরে নিন যে এগুলি আমরা জেএসএন-তে বস্তুগুলিকে সিরিয়ালাইজ করার জন্য ব্যবহার করি serial রাইটওজেক্টফিল্ড যদি অবজেক্ট ম্যাপারের সাথে নিবন্ধিত হয় তবে অবজেক্টের নিজস্ব সিরিয়ালাইজার ব্যবহার করে; যদি তা না হয়, তবে এটি এটিকে পজো হিসাবে সিরিয়াল করে তোলে। WritNumberFeld একচেটিয়াভাবে আদিম হিসাবে আদিমিকে গ্রহণ করে।

public class ClassroomSerializer extends StdSerializer<Classroom> {
    public ClassroomSerializer(Class<Classroom> t) {
        super(t);
    }

    @Override
    public void serialize(Classroom value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonGenerationException {
        jgen.writeStartObject();
        jgen.writeObjectField("double1-Object", value.double1);
        jgen.writeNumberField("double1-Number", value.double1);
        jgen.writeObjectField("Double1-Object", value.Double1);
        jgen.writeNumberField("Double1-Number", value.Double1);
        jgen.writeObjectField("student1", value.student1);
        jgen.writeEndObject();
    }
}

public class StudentSerializer extends StdSerializer<Student> {
    public StudentSerializer(Class<Student> t) {
        super(t);
    }

    @Override
    public void serialize(Student value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonGenerationException {
        jgen.writeStartObject();
        jgen.writeObjectField("double2-Object", value.double2);
        jgen.writeNumberField("double2-Number", value.double2);
        jgen.writeObjectField("Double2-Object", value.Double2);
        jgen.writeNumberField("Double2-Number", value.Double2);
        jgen.writeEndObject();
    }
}

3) সিম্পলমডুলিতে ডেসিমালফর্ম্যাট আউটপুট প্যাটার্ন সহ কেবল একটি ডাবলশিরাইজারের নিবন্ধন করুন ###,##0.000এবং আউটপুটটি হ'ল:

{
  "double1" : 1234.5678,
  "Double1" : {
    "value" : "91,011.121"
  },
  "student1" : {
    "double2" : 1920.2122,
    "Double2" : {
      "value" : "2,324.253"
    }
  }
}

আপনি দেখতে পাচ্ছেন যে ডাবলসের জন্য ডাবলশেরিজার ব্যবহার করে এবং ডাবলসের জন্য নিয়মিত স্ট্রিং ফর্ম্যাট ব্যবহার করে পজো সিরিয়ালাইজেশন ডাবল এবং ডাবলের মধ্যে পার্থক্য রাখে।

4) ডাবলশিরাইজার এবং ক্লাসরুমেরাইজারাইজার নিবন্ধন করুন, স্টুডেন্টরিশাইজার ছাড়াই। আমরা প্রত্যাশা করি আউটপুটটি এমন যে আমরা যদি কোনও বস্তু হিসাবে ডাবল লিখি তবে এটি একটি ডাবলের মতো আচরণ করে এবং যদি আমরা একটি সংখ্যা হিসাবে একটি ডাবল লিখি তবে এটি একটি ডাবলের মতো আচরণ করে। শিক্ষার্থীর উদাহরণ ভেরিয়েবলটি একটি পজো হিসাবে লেখা উচিত এবং এটি নিবন্ধভুক্ত না হওয়ায় উপরের প্যাটার্নটি অনুসরণ করা উচিত।

{
  "double1-Object" : {
    "value" : "1,234.568"
  },
  "double1-Number" : 1234.5678,
  "Double1-Object" : {
    "value" : "91,011.121"
  },
  "Double1-Number" : 91011.1213,
  "student1" : {
    "double2" : 1920.2122,
    "Double2" : {
      "value" : "2,324.253"
    }
  }
}

5) সমস্ত সিরিয়ালাইজার নিবন্ধন করুন। আউটপুটটি হ'ল:

{
  "double1-Object" : {
    "value" : "1,234.568"
  },
  "double1-Number" : 1234.5678,
  "Double1-Object" : {
    "value" : "91,011.121"
  },
  "Double1-Number" : 91011.1213,
  "student1" : {
    "double2-Object" : {
      "value" : "1,920.212"
    },
    "double2-Number" : 1920.2122,
    "Double2-Object" : {
      "value" : "2,324.253"
    },
    "Double2-Number" : 2324.2526
  }
}

ঠিক যেমন প্রত্যাশিত

আরেকটি গুরুত্বপূর্ণ দ্রষ্টব্য: যদি আপনার কাছে একই মডিউলটির সাথে নিবন্ধিত একই শ্রেণীর জন্য একাধিক সিরিয়ালাইজার থাকে, তবে মডিউলটি সম্প্রতি শ্রেণীর তালিকায় যুক্ত হওয়া শ্রেণীর জন্য সিরিয়াল নির্বাচন করবে। এটি ব্যবহার করা উচিত নয় - এটি বিভ্রান্তিকর এবং আমি নিশ্চিত না যে এটি কতটা সামঞ্জস্যপূর্ণ

নৈতিক: আপনি যদি নিজের অবজেক্টে আদিমগুলির সিরিয়ালাইজেশন কাস্টমাইজ করতে চান তবে আপনাকে অবশ্যই সেই বস্তুর জন্য নিজস্ব সিরিয়ালাইজার লিখতে হবে। আপনি POJO জ্যাকসন সিরিয়ালাইজেশন উপর নির্ভর করতে পারবেন না।


ক্লাসরুমের উপস্থিতিগুলি হ্যান্ডেল করার জন্য আপনি কীভাবে শ্রেণীকক্ষশরীণকারীকে নিবন্ধভুক্ত করবেন?
Trismegistos

5

জ্যাকসনের জেএসন ভিউগুলি আপনার প্রয়োজনীয়তা অর্জনের সহজ উপায় হতে পারে, বিশেষত যদি আপনার জেএসএন ফর্ম্যাটে কিছুটা নমনীয়তা থাকে।

যদি {"id":7, "itemNr":"TEST", "createdBy":{id:3}}গ্রহণযোগ্য উপস্থাপনা হয় তবে খুব সামান্য কোড সহ এটি অর্জন করা খুব সহজ হবে।

আপনি কেবলমাত্র দর্শকের অংশ হিসাবে ব্যবহারকারীর নাম ক্ষেত্রটি বর্ননা করবেন এবং আপনার সিরিয়ালাইজেশনের অনুরোধে একটি পৃথক ভিউ নির্দিষ্ট করবেন (অন-টিকা ক্ষেত্রগুলি ডিফল্টরূপে অন্তর্ভুক্ত করা হবে)

উদাহরণস্বরূপ: মতামত সংজ্ঞায়িত করুন:

public class Views {
    public static class BasicView{}
    public static class CompleteUserView{}
}

ব্যবহারকারীকে টিকা দিন:

public class User {
    public final int id;

    @JsonView(Views.CompleteUserView.class)
    public final String name;

    public User(int id, String name) {
        this.id = id;
        this.name = name;
    }
}

এবং সিরিয়ালিয়াস এমন একটি দৃশ্যের জন্য অনুরোধ করছে যাতে আপনি যে ক্ষেত্রটি আড়াল করতে চান তা ধারণ করে না (অ-টীকাকৃত ক্ষেত্রগুলি ডিফল্টরূপে ক্রমিকায়িত করা হয়):

objectMapper.getSerializationConfig().withView(Views.BasicView.class);

আমি জ্যাকসন জেএসএন ভিউগুলি ব্যবহার করা শক্ত বলে মনে করি এবং এই সমস্যার ভাল সমাধান পেতে পারি না।
জোনাস

জোনাস - আমি একটি উদাহরণ যুক্ত করেছি। একই উপায়ে বিভিন্ন উপায়ে সিরিয়ালকরণের জন্য আমি দর্শনগুলি একটি দুর্দান্ত সমাধান পেয়েছি।
পল এম

একটি ভাল উদাহরণ জন্য ধন্যবাদ। এটি এখন পর্যন্ত সেরা সমাধান। তবে createdByকোনও বস্তুর পরিবর্তে মান হিসাবে পাওয়ার কোনও উপায় নেই ?
জোনাস

setSerializationView()অবহেলিত বলে মনে হচ্ছে তাই mapper.viewWriter(JacksonViews.ItemView.class).writeValue(writer, myItem);পরিবর্তে আমি ব্যবহার করেছি ।
জোনাস

আমি jsonviews ব্যবহার করে সন্দেহ। দৃশ্যের সন্ধানের আগে আমি একটি দ্রুত এবং নোংরা সমাধানটি হ'ল কেবল আমার পছন্দসই বৈশিষ্ট্যগুলি একটি মানচিত্রে অনুলিপি করা এবং তারপরে মানচিত্রটি সিরিয়াল করা।
পল এম

5

আমার ক্ষেত্রে (স্প্রিং 3.2.4 এবং জ্যাকসন 2.3.1), কাস্টম সিরিয়ালাইজারের জন্য এক্সএমএল কনফিগারেশন:

<mvc:annotation-driven>
    <mvc:message-converters register-defaults="false">
        <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
            <property name="objectMapper">
                <bean class="org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean">
                    <property name="serializers">
                        <array>
                            <bean class="com.example.business.serializer.json.CustomObjectSerializer"/>
                        </array>
                    </property>
                </bean>
            </property>
        </bean>
    </mvc:message-converters>
</mvc:annotation-driven>

অব্যক্ত পদ্ধতিতে কোনও কিছুর দ্বারা আবার ডিফল্টে ওভাররাইট করা হয়েছিল।

এটি আমার পক্ষে কাজ করেছে:

CustomObject.java

@JsonSerialize(using = CustomObjectSerializer.class)
public class CustomObject {

    private Long value;

    public Long getValue() {
        return value;
    }

    public void setValue(Long value) {
        this.value = value;
    }
}

CustomObjectSerializer.java

public class CustomObjectSerializer extends JsonSerializer<CustomObject> {

    @Override
    public void serialize(CustomObject value, JsonGenerator jgen,
        SerializerProvider provider) throws IOException,JsonProcessingException {
        jgen.writeStartObject();
        jgen.writeNumberField("y", value.getValue());
        jgen.writeEndObject();
    }

    @Override
    public Class<CustomObject> handledType() {
        return CustomObject.class;
    }
}

<mvc:message-converters>(...)</mvc:message-converters>আমার সমাধানে কোনও এক্সএমএল কনফিগারেশন ( ) দরকার নেই।


1

যদি আপনার কাস্টম সিরিয়ালাইজারে আপনার কেবলমাত্র প্রয়োজনটি nameক্ষেত্রটি সিরিয়ালাইজিং এড়ানো যায় User, এটিকে ক্ষণস্থায়ী হিসাবে চিহ্নিত করুন । জ্যাকসন হবে না ধারাবাহিকভাবে বা deserialize অস্থায়ী ক্ষেত্রগুলিকে ।

[আরও দেখুন: জাভা কেন ক্ষণস্থায়ী ক্ষেত্র আছে? ]


আমি কোথায় এটি চিহ্নিত করব? ইন User-class? তবে আমি সমস্ত ব্যবহারকারী-বস্তুগুলিকেও সিরিয়ালিয়াল করব। উদাহরণস্বরূপ, কেবলমাত্র প্রথমে সমস্ত সিরিয়ালাইজ করুন items(কেবলমাত্র userIdব্যবহারকারী সামগ্রীর উল্লেখ হিসাবে) এবং তারপরে সমস্ত সিরিয়ালাইজ করুন users। এই ক্ষেত্রে আমি Userক্লাসে ফিলগুলি চিহ্নিত করতে পারি না ।
জোনাস

এই নতুন তথ্যের আলোকে, এই পদ্ধতিটি আপনার পক্ষে কাজ করবে না। দেখে মনে হচ্ছে জ্যাকসন কাস্টম সিরিয়ালাইজারের জন্য আরও তথ্যের সন্ধান করছেন (হ্যান্ডল্ডটাইপ () পদ্ধতির ওভাররাইডিং দরকার?)
মাইক জি

হ্যাঁ, তবে handledType()আমি যে ডকুমেন্টেশনের সাথে লিঙ্ক করেছি তাতে পদ্ধতিটি লক্ষ করা যায় এবং যখন গ্রহপৃষ্ঠীর প্রয়োগের handledType()জন্য উত্পন্ন হয় কোনটি উত্পন্ন হয় না, তাই আমি বিভ্রান্ত হয়ে পড়েছি।
জোনাস

আমি নিশ্চিত নই কারণ আপনি সংযুক্ত উইকিটি এটি উল্লেখ করে না, তবে 1.5.1.1 সংস্করণে একটি হ্যান্ডল্ডটাইপ () রয়েছে এবং ব্যতিক্রমটি মনে হয় যে পদ্ধতিটি অনুপস্থিত বা অবৈধ (বেস ক্লাসটি পদ্ধতিটি বাতিল করে দেয়) অভিযোগ করছে। জ্যাকসন.কোডাহস.আর.সি.
মাইক জি


0

আপনার ক্ষেত্রে সমস্যাটি হ'ল আইটেমসিরালাইজারটি হ্যান্ডলডটাইপ পদ্ধতিটি () কে অনুপস্থিত যা জসনসিরাইজার থেকে ওভাররাইড করা দরকার

    public class ItemSerializer extends JsonSerializer<Item> {

    @Override
    public void serialize(Item value, JsonGenerator jgen,
            SerializerProvider provider) throws IOException,
            JsonProcessingException {
        jgen.writeStartObject();
        jgen.writeNumberField("id", value.id);
        jgen.writeNumberField("itemNr", value.itemNr);
        jgen.writeNumberField("createdBy", value.user.id);
        jgen.writeEndObject();
    }

   @Override
   public Class<Item> handledType()
   {
    return Item.class;
   }
}

সুতরাং আপনি স্পষ্ট ত্রুটি পেয়ে যাচ্ছেন যে হ্যান্ডেলডটাইপ () সংজ্ঞায়িত নয় is

Exception in thread "main" java.lang.IllegalArgumentException: JsonSerializer of type com.example.ItemSerializer does not define valid handledType() 

আশা করি এটি কাউকে সাহায্য করবে। আমার উত্তর পড়ার জন্য ধন্যবাদ।

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