গসন: এনোটোটেশন ছাড়াই সিরিয়ালাইজেশন থেকে নির্দিষ্ট ক্ষেত্রগুলি কীভাবে বাদ দেওয়া যায়


413

আমি গসন শিখার চেষ্টা করছি এবং আমি মাঠের বাদ দিয়ে লড়াই করছি। এখানে আমার ক্লাস

public class Student {    
  private Long                id;
  private String              firstName        = "Philip";
  private String              middleName       = "J.";
  private String              initials         = "P.F";
  private String              lastName         = "Fry";
  private Country             country;
  private Country             countryOfBirth;
}

public class Country {    
  private Long                id;
  private String              name;
  private Object              other;
}

আমি জিসনবিল্ডারটি ব্যবহার করতে পারি এবং ফিল্ডের নামের জন্য একটি এক্সক্লুশনস্ট্র্যাজি যুক্ত করতে পারি firstNameবা countryতেমন কিছু ক্ষেত্রের বৈশিষ্ট্য বাদ দিতেও আমি পরিচালনা করতে পারি নাcountry.name

পদ্ধতিটি ব্যবহার করে public boolean shouldSkipField(FieldAttributes fa), ফিল্ডঅ্যাট্রিবিউটে ফিল্টারটির মতো ফিল্টারটির সাথে মিল রাখতে পর্যাপ্ত তথ্য নেইcountry.name

PS: আমি এটিকে উন্নত করতে এবং ক্ষেত্রগুলি ফিল্টার করার জন্য RegEx ব্যবহার করতে চাইলে আমি টীকাগুলি এড়াতে চাই।

সম্পাদনা : স্ট্রটস 2 জেএসএন প্লাগইনের আচরণ অনুকরণ করা সম্ভব কিনা তা দেখার চেষ্টা করছি

গসন ব্যবহার করে

<interceptor-ref name="json">
  <param name="enableSMD">true</param>
  <param name="excludeProperties">
    login.password,
    studentList.*\.sin
  </param>
</interceptor-ref>

সম্পাদনা করুন: আমি নিম্নলিখিতটি যুক্ত করে আবার প্রশ্নটি খুললাম:

আমি এই সমস্যাটি আরও পরিষ্কার করতে একই ধরণের সাথে একটি দ্বিতীয় ক্ষেত্র যুক্ত করেছি। মূলত আমি বাদ দিতে চাই country.nameতবে চাই না countrOfBirth.name। আমি দেশকে কোনও প্রকার হিসাবে বাদ দিতে চাই না। সুতরাং প্রকারগুলি একই হ'ল এটি অবজেক্ট গ্রাফের আসল জায়গা যা আমি পয়েন্টপয়েন্ট করতে এবং বাদ দিতে চাই।


1
সংস্করণ ২.২ অনুসারে এখনও আমি বাদ দিতে ক্ষেত্রের কোনও পথ নির্দিষ্ট করতে পারি না। ফ্লেক্সসন.সোর্সফোর্জন.নেট একটি ভাল বিকল্প বলে মনে করে।
Liviu টি।

বেশ অনুরূপ প্রশ্নের আমার উত্তরটি একবার দেখুন । এটি JsonSerializerকোনও প্রকারের জন্য একটি কাস্টম তৈরির উপর ভিত্তি করে - Countryআপনার ক্ষেত্রে - যার জন্য এমন একটি প্রয়োগ করা হয় ExclusionStrategyযা কোন ক্ষেত্রকে সিরিয়ালায়িত করার সিদ্ধান্ত নেয়।
পিরহো

উত্তর:


625

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

আপনি যদি নামটি সিরিয়ালযুক্ত জাসনটিতে প্রদর্শিত না করতে চান তবে এটিকে একটি ক্ষণস্থায়ী কীওয়ার্ড দিন, যেমন:

private transient String name;

গসন ডকুমেন্টেশনে আরও বিশদ


6
এটি প্রায় বর্জনীয় টীকা হিসাবে একই জিনিস এটি শ্রেণীর সমস্ত দৃষ্টান্তের জন্য প্রযোজ্য। আমি রানটাইম গতিশীল বর্জন চেয়েছিলাম। আমি কিছু ক্ষেত্রে হালকা / সীমাবদ্ধ প্রতিক্রিয়া সরবরাহ করার জন্য কিছু ক্ষেত্র বাদ দিয়ে যেতে চাই এবং অন্যগুলিতে আমি সম্পূর্ণ বস্তুটি সিরিয়ালীকৃত করতে চাই
লিভিউ টি।

34
একটি বিষয় লক্ষণীয় যে ক্ষণস্থায়ী প্রভাব সিরিয়ালাইজেশন এবং deserialization উভয়ই। এটি JSON এ উপস্থিত থাকা সত্ত্বেও, বস্তুটিতে সিরিয়ালযুক্ত হওয়া থেকে মানটিও নির্গত করে।
কং

3
transientপরিবর্তে ব্যবহার করার ক্ষেত্রে সমস্যাটি @Exposeহ'ল আপনাকে এখনও নিজের ক্লায়েন্টের কাছে এমন সমস্ত ক্ষেত্রের সাথে একটি পজো মক করতে হবে যা সম্ভবত আসতে পারে projects প্রজেক্টগুলির মধ্যে ভাগ করা হতে পারে এমন ব্যাক-এন্ড এপিআইয়ের ক্ষেত্রে, এটি সমস্যাযুক্ত হতে পারে অতিরিক্ত ক্ষেত্র যুক্ত করা হয়। মূলত এটি ক্ষেত্রগুলিকে ব্ল্যাকলিস্টিংয়ের তুলনায় শ্বেত তালিকাভুক্ত করা হচ্ছে।
theblang

11
এই পদ্ধতিরটি আমার পক্ষে কার্যকর হয়নি, কারণ এটি ক্ষেত্রটি কেবলমাত্র জিএসএন সিরিয়ালাইজেশন থেকে বাদ দেয়নি, তবে ক্ষেত্রটিকে অভ্যন্তরীণ অ্যাপ সিরিয়ালাইজেশন (সিরিয়ালাইজেবল ইন্টারফেস ব্যবহার করে) থেকে বাদ দিয়েছে।
pkk

8
ক্ষণস্থায়ী একটি ক্ষেত্রের সিরিয়ালাইজেশন এবং নির্ণয়কে বাধা দেয়। এটি আমার প্রয়োজনের সাথে মেলে না।
লেনিক্স

318

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

@Expose private Long id;

আপনি ক্রমিক করতে চান না এমন কোনও ক্ষেত্র ছেড়ে দিন। তারপরে এইভাবে আপনার জিসন অবজেক্টটি তৈরি করুন:

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

95
"নট এক্সপোজ" এর মতো কিছু পাওয়া এবং কেবল সেই ক্ষেত্রে কেবল একটি ক্ষেত্র বাদে সমস্ত ক্ষেত্রটি সিরিয়াল করা উচিত এবং এগুলির সমস্তটিতে টীকাগুলি যুক্ত করা বাড়াবাড়ি?
ড্যানিল শেভলেভ

2
@ দাশ আমার সম্প্রতি একটি দৃশ্য ছিল। এটি একটি কাস্টম এক্সক্লুশনস্ট্রেজি লিখতে খুব সহজ ছিল যা ঠিক এটি করেছিল। নিশান্তের উত্তর দেখুন। একমাত্র সমস্যা ছিল স্কিপক্লাস বনাম স্কিপফিল্ডের সাথে একগুচ্ছ ধারক ক্লাস এবং ফিডাল অন্তর্ভুক্ত করা (ক্ষেত্রগুলি ক্লাস হতে পারে ...)
কীজার

1
@ দাশ আমার উত্তর নীচে ঠিক তা করে।
ডেরেক শকি

কি দুর্দান্ত সমাধান। আমি এমন একটি দৃশ্যে যাচ্ছিলাম যেখানে আমি ফিল্ডটি ডিস্কে সিরিয়ালযুক্ত করতে চাইছি তবে এটি জিএসসনের মাধ্যমে সার্ভারে প্রেরণ করার সময় এড়ানো হবে। পারফেক্ট, ধন্যবাদ!
Slynk

1
@ ড্যানিলিল আপনি @ এক্সপোজ (সিরিয়ালাইজ = মিথ্যা, ডিসিরিয়ালাইজেশন = মিথ্যা) ব্যবহার করতে সক্ষম হবেন
এইচআরকে

237

সুতরাং, আপনি বাদ দিতে চান firstNameএবং country.name। আপনার ExclusionStrategyদেখতে কেমন হওয়া উচিত তা এখানে

    public class TestExclStrat implements ExclusionStrategy {

        public boolean shouldSkipClass(Class<?> arg0) {
            return false;
        }

        public boolean shouldSkipField(FieldAttributes f) {

            return (f.getDeclaringClass() == Student.class && f.getName().equals("firstName"))||
            (f.getDeclaringClass() == Country.class && f.getName().equals("name"));
        }

    }

আপনি যদি ঘনিষ্ঠভাবে দেখতে পান তবে এটির trueজন্য ফিরে আসে Student.firstNameএবং Country.nameএটিই আপনি বাদ দিতে চান।

আপনার ExclusionStrategyএটিকে এভাবে প্রয়োগ করা দরকার ,

    Gson gson = new GsonBuilder()
        .setExclusionStrategies(new TestExclStrat())
        //.serializeNulls() <-- uncomment to serialize NULL fields as well
        .create();
    Student src = new Student();
    String json = gson.toJson(src);
    System.out.println(json);

এটি ফিরে আসে:

{ "middleName": "J.", "initials": "P.F", "lastName": "Fry", "country": { "id": 91}}

আমি ধরে নিই যে দেশের id = 91Lক্লাসটি শিক্ষার্থীর ক্লাসে শুরু হয়েছিল।


আপনি অভিনব পেতে পারেন। উদাহরণস্বরূপ, আপনি এমন কোনও ক্ষেত্র যাতে তার নামে "নাম" স্ট্রিং রয়েছে তা ক্রমিক করতে চান না। এটা কর:

public boolean shouldSkipField(FieldAttributes f) {
    return f.getName().toLowerCase().contains("name"); 
}

এটি ফিরে আসবে:

{ "initials": "P.F", "country": { "id": 91 }}

সম্পাদনা: অনুরোধ হিসাবে আরও তথ্য যুক্ত করা হয়েছে।

এটি ExclusionStrategyকাজটি করবে, তবে আপনাকে "ফুললি কোয়ালিফাইড ফিল্ডের নাম" পাস করতে হবে। নিচে দেখ:

    public class TestExclStrat implements ExclusionStrategy {

        private Class<?> c;
        private String fieldName;
        public TestExclStrat(String fqfn) throws SecurityException, NoSuchFieldException, ClassNotFoundException
        {
            this.c = Class.forName(fqfn.substring(0, fqfn.lastIndexOf(".")));
            this.fieldName = fqfn.substring(fqfn.lastIndexOf(".")+1);
        }
        public boolean shouldSkipClass(Class<?> arg0) {
            return false;
        }

        public boolean shouldSkipField(FieldAttributes f) {

            return (f.getDeclaringClass() == c && f.getName().equals(fieldName));
        }

    }

আমরা কীভাবে এটি সাধারণভাবে ব্যবহার করতে পারি তা এখানে।

    Gson gson = new GsonBuilder()
        .setExclusionStrategies(new TestExclStrat("in.naishe.test.Country.name"))
        //.serializeNulls()
        .create();
    Student src = new Student();
    String json = gson.toJson(src);
    System.out.println(json); 

এটি ফিরে আসে:

{ "firstName": "Philip" , "middleName": "J.", "initials": "P.F", "lastName": "Fry", "country": { "id": 91 }}

উত্তর দেওয়ার জন্য আপনাকে ধন্যবাদ। আমি যা চাই তা হল একটি এক্সক্লুশনস্ট্রেজি তৈরি করা যা এর মতো স্ট্রিং নিতে পারে country.nameএবং ক্ষেত্রটি nameসিরিয়াল করার সময় কেবল ক্ষেত্রটি বাদ দিতে পারে country। দেশ শ্রেণীর একটি সম্পত্তি নামের দেশ রয়েছে এমন প্রতিটি শ্রেণিতে প্রয়োগ করার পক্ষে এটি যথেষ্ট জেনারেল হওয়া উচিত। আমি প্রতিটি শ্রেণীর জন্য একটি এক্সক্লুশন স্ট্র্যাজি তৈরি করতে চাই না
Liviu T.

@ লিভিউ টি। আমি উত্তর আপডেট করেছি। এটি জেনেরিক পদ্ধতির লাগে। আপনি আরও সৃজনশীল পেতে পারেন, তবে আমি এটিকে প্রাথমিক রেখেছি।
নিশান্ত

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

খালি মান আছে এমন ক্ষেত্রগুলি বাদ দেওয়ার কোনও উপায় আছে কি?
ইউসুফ কে।

12
এই উত্তরটি পছন্দসই উত্তর হিসাবে চিহ্নিত করা উচিত। অন্যান্য উত্তরগুলির তুলনায় বর্তমানে বর্তমানে বেশি ভোট রয়েছে, এই সমাধানের জন্য আপনাকে শিম শ্রেণি পরিবর্তন করার প্রয়োজন হয় না। এটি একটি বিশাল প্লাস। যদি অন্য কেউ একই শিমের বর্গ ব্যবহার করে, এবং আপনি এমন একটি ক্ষেত্র চিহ্নিত করেছেন যা তারা "ক্ষণস্থায়ী" হিসাবে অবিরত থাকতে চান?
ব্যবহারকারী 64141

221

সমস্ত উপলভ্য উত্তর পড়ার পরে আমি জানতে পেরেছি যে আমার ক্ষেত্রে সর্বাধিক নমনীয় ছিল কাস্টম @Excludeটীকাটি ব্যবহার করা । সুতরাং, আমি এটির জন্য সহজ কৌশল বাস্তবায়িত করেছি (আমি সমস্ত ক্ষেত্র ব্যবহার করে চিহ্নিত @Exposeকরতে চাইনি বা transientঅ্যাপটিতে যে বিরোধী তা আমি ব্যবহার করতে চাইনিSerializable সিরিয়ালাইজেশনের ):

টীকা:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Exclude {
}

কৌশল:

public class AnnotationExclusionStrategy implements ExclusionStrategy {

    @Override
    public boolean shouldSkipField(FieldAttributes f) {
        return f.getAnnotation(Exclude.class) != null;
    }

    @Override
    public boolean shouldSkipClass(Class<?> clazz) {
        return false;
    }
}

ব্যবহার:

new GsonBuilder().setExclusionStrategies(new AnnotationExclusionStrategy()).create();

16
অতিরিক্ত নোট হিসাবে, আপনি যদি কেবলমাত্র সিরিয়ালাইজেশন বা কেবল deserialization জন্য আপনার বর্জন কৌশল ব্যবহার করতে চান তবে ব্যবহার করুন: addSerializationExclusionStrategyবা addDeserializationExclusionStrategyতার পরিবর্তেsetExclusionStrategies
GLee

9
পারফেক্ট! অস্থায়ী সমাধান নয় কাজ আমার জন্য, কারণ আমি ডিবি জন্য অধিরাজ্য ব্যবহার করছি করে এবং আমি শুধুমাত্র Gson থেকে একটি ক্ষেত্র বাদ দেওয়ার বিষয়ে, কিন্তু না অধিরাজ্য (কোনটা অস্থায়ী আছে)
Marcio Granzotto

3
এটি গ্রহণযোগ্য উত্তর হওয়া উচিত। নাল ক্ষেত্রগুলি উপেক্ষা করার জন্য কেবল পরিবর্তন f.getAnnotation(Exclude.class) != nullকরুনf.getAnnotation(Exclude.class) == null
শার্প এজ

3
transientঅন্যান্য লাইব্রেরির প্রয়োজনের কারণে আপনি যখন ব্যবহার করতে পারবেন না তখন দুর্দান্ত । ধন্যবাদ!
মার্টিন ডি

1
আমার জন্যও দুর্দান্ত কারণ অ্যান্ড্রয়েড আমার ক্লাসগুলি ক্রিয়াকলাপগুলির মধ্যে ক্রমিক করে তোলে তবে আমি যখন জিএসএন ব্যবহার করি তখন কেবল সেগুলি বাদ দেওয়া চাই। এটি অন্যদের কাছে প্রেরণের জন্য এগুলি গুটিয়ে রাখতে না পারা পর্যন্ত আমার অ্যাপটি একইভাবে কাজ করে চলেছে।
ThePartyTurtle

81

আমি এই ইস্যুতে দৌড়েছি, যার মধ্যে আমার খুব কম ক্ষেত্র ছিল আমি কেবল সিরিয়ালাইজেশন থেকে বাদ দিতে চেয়েছিলাম, তাই আমি মোটামুটি সহজ সমাধান বিকাশ করেছি যা গসনের ব্যবহার করে @Expose কাস্টম বর্জন কৌশলগুলি সহ ।

ব্যবহারের একমাত্র অন্তর্নিহিত উপায় @Exposeহ'ল সেট করা GsonBuilder.excludeFieldsWithoutExposeAnnotation(), তবে নামটি সূচিত করে যেমন একটি স্পষ্ট ছাড়াই ক্ষেত্র@Expose উপেক্ষা করা হবে। যেহেতু আমি কেবলমাত্র কয়েকটি ক্ষেত্রকে বাদ দিতে চেয়েছিলাম, তাই প্রতিটি ক্ষেত্রটিতে টীকা যুক্ত করার সম্ভাবনাটি খুব জটিল ome

আমি কার্যকরভাবে বিপরীতটি চেয়েছিলাম, যাতে আমি স্পষ্টভাবে @Exposeএটিকে বাদ না দিয়ে সমস্ত কিছু অন্তর্ভুক্ত ছিল । আমি এটি সম্পাদন করতে নিম্নলিখিত বর্জন কৌশলগুলি ব্যবহার করেছি:

new GsonBuilder()
        .addSerializationExclusionStrategy(new ExclusionStrategy() {
            @Override
            public boolean shouldSkipField(FieldAttributes fieldAttributes) {
                final Expose expose = fieldAttributes.getAnnotation(Expose.class);
                return expose != null && !expose.serialize();
            }

            @Override
            public boolean shouldSkipClass(Class<?> aClass) {
                return false;
            }
        })
        .addDeserializationExclusionStrategy(new ExclusionStrategy() {
            @Override
            public boolean shouldSkipField(FieldAttributes fieldAttributes) {
                final Expose expose = fieldAttributes.getAnnotation(Expose.class);
                return expose != null && !expose.deserialize();
            }

            @Override
            public boolean shouldSkipClass(Class<?> aClass) {
                return false;
            }
        })
        .create();

এখন আমি সহজেই কয়েকটি ক্ষেত্র @Expose(serialize = false)বা @Expose(deserialize = false)টীকাগুলি বাদ দিতে পারি (নোট করুন যে উভয় @Exposeবৈশিষ্ট্যের জন্য ডিফল্ট মান true)) আপনি অবশ্যই ব্যবহার করতে পারেন @Expose(serialize = false, deserialize = false), তবে এটি ক্ষেত্রটি ঘোষণার মাধ্যমে আরও সংক্ষিপ্তভাবে সম্পন্ন করা হয়েছে transient(যা এখনও এই কাস্টম বর্জন কৌশলগুলির সাথে কার্যকর হয়)।


দক্ষতার জন্য, আমি ক্ষণস্থায়ী না হয়ে @ এক্সপোজ (সিরিয়ালাইজ = ভুয়া, deserialize = মিথ্যা) ব্যবহারের জন্য একটি মামলা দেখতে পাচ্ছি।
পাইগো 18

1
@ পিয়েগো আপনি কি এর উপর প্রসারিত করতে পারেন? আমি এখন বহু বছর জিসন ব্যবহার করা থেকে সরিয়ে এসেছি এবং টীকাটিকে ক্ষণস্থায়ী চিহ্নিত করার চেয়ে কেন টীকাটি আরও কার্যকর তা আমি বুঝতে পারি না।
ডেরেক শকি

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

18

আপনি গসন সহ জসন ট্রি অন্বেষণ করতে পারেন।

এরকম কিছু চেষ্টা করুন:

gson.toJsonTree(student).getAsJsonObject()
.get("country").getAsJsonObject().remove("name");

আপনি কিছু বৈশিষ্ট্য যুক্ত করতে পারেন:

gson.toJsonTree(student).getAsJsonObject().addProperty("isGoodStudent", false);

জিএসন ২.২.৪ দিয়ে পরীক্ষা করা হয়েছে।


3
আমি অবাক হয়েছি যে আপনি যদি কোনও জটিল সম্পত্তি থেকে অপসারণ করতে চান যা মুছে ফেলার আগে পার্স করতে হয় তবে এটি খুব বেশি পারফরম্যান্সের হিট কিনা। থটস?
বেন

অবশ্যই কোনও স্কেলযোগ্য সমাধান নয়, আপনি যদি নিজের অবজেক্টের কাঠামো পরিবর্তন করেন বা স্টাফ যুক্ত / অপসারণ করেন তবে আপনার যে সমস্ত মাথা ব্যাথা হওয়া দরকার তা কল্পনা করুন।
codenamezero

16

এই কার্যকারিতাটি সমর্থন করার জন্য আমি একটি ক্লাস কারখানা নিয়ে এসেছি। ক্ষেত্র বা শ্রেণিগুলির যে কোনও সংমিশ্রনে আপনি বাদ দিতে চান Pass

public class GsonFactory {

    public static Gson build(final List<String> fieldExclusions, final List<Class<?>> classExclusions) {
        GsonBuilder b = new GsonBuilder();
        b.addSerializationExclusionStrategy(new ExclusionStrategy() {
            @Override
            public boolean shouldSkipField(FieldAttributes f) {
                return fieldExclusions == null ? false : fieldExclusions.contains(f.getName());
            }

            @Override
            public boolean shouldSkipClass(Class<?> clazz) {
                return classExclusions == null ? false : classExclusions.contains(clazz);
            }
        });
        return b.create();

    }
}

ব্যবহার করতে, দুটি তালিকা তৈরি করুন (প্রতিটি optionচ্ছিক) এবং আপনার জিএসওএন অবজেক্ট তৈরি করুন:

static {
 List<String> fieldExclusions = new ArrayList<String>();
 fieldExclusions.add("id");
 fieldExclusions.add("provider");
 fieldExclusions.add("products");

 List<Class<?>> classExclusions = new ArrayList<Class<?>>();
 classExclusions.add(Product.class);
 GSON = GsonFactory.build(null, classExclusions);
}

private static final Gson GSON;

public String getSomeJson(){
    List<Provider> list = getEntitiesFromDatabase();
    return GSON.toJson(list);
}

অবশ্যই, গুনটির সম্পূর্ণরূপে যোগ্যতাসম্পন্ন নামটি দেখার জন্য এটি সংশোধন করা যেতে পারে এবং ম্যাচের পরে তা বাদ দেওয়া যায় ...
ডোমেনিক ডি

আমি উদাহরণের নীচে করছি। এটি কাজ করছে না। প্লিজ বেসরকারী স্থিতিশীল চূড়ান্ত গসন জিএসওনের পরামর্শ দেয়; স্ট্যাটিক {তালিকা <স্ট্রিং> ফিল্ড এক্সক্লুয়েন্স = নতুন অ্যারেলিস্ট <স্ট্রিং> (); fieldExclusions.add ( "ID"); জিএসএন = জিসনফ্যাক্টরি.বিল্ড (ফিল্ডএক্সক্লুশনস, নাল); } প্রাইভেট স্ট্যাটিক স্ট্রিং getSomeJson () {স্ট্রিং jsonStr = "[{\" আইডি \ ": 111, \" নাম \ ": pra" প্রবীণ \ ", \" বয়স \ ": 16}, {id" আইডি \ ": 222, \ "নাম \": \ "Prashant \", \ "বয়স \": 20}] "; রিটার্ন jsonStr; } পাবলিক স্ট্যাটিক অকার্যকর প্রধান (স্ট্রিং [] আরগস) {স্ট্রিং জসনএসটিআর = getSomeJson (); System.out.println (GSON.toJson (jsonStr)); }
প্রবীণ হীরমঠ

13

আমি কাস্টম টিকা দিয়ে এই সমস্যাটি সমাধান করেছি। এটি আমার "স্কিপসিরালাইজেশন" টিকাশনের শ্রেণি:

@Target (ElementType.FIELD)
public @interface SkipSerialisation {

}

এবং এটি আমার গসনবিল্ডার:

gsonBuilder.addSerializationExclusionStrategy(new ExclusionStrategy() {

  @Override public boolean shouldSkipField (FieldAttributes f) {

    return f.getAnnotation(SkipSerialisation.class) != null;

  }

  @Override public boolean shouldSkipClass (Class<?> clazz) {

    return false;
  }
});

উদাহরণ:

public class User implements Serializable {

  public String firstName;

  public String lastName;

  @SkipSerialisation
  public String email;
}

5
গসন: টিকা ছাড়াই
বেন

3
@Retention(RetentionPolicy.RUNTIME)আপনার টীকাতেও আপনার যুক্ত করা উচিত ।
ডেভিড নোভোক

9

অথবা কোন ক্ষেত্রগুলি এর সাথে প্রকাশ করবে না তা বলতে পারেন:

Gson gson = gsonBuilder.excludeFieldsWithModifiers(Modifier.TRANSIENT).create();

গুণতে আপনার শ্রেণিতে:

private **transient** boolean nameAttribute;

17
অস্থায়ী এবং স্থির ক্ষেত্রগুলি ডিফল্টরূপে বাদ দেওয়া হয়; এর জন্য কল করার দরকার নেই excludeFieldsWithModifiers()
ডেরেক শকি

9

আমি এই কৌশলটি ব্যবহার করেছি: আমি প্রতিটি ক্ষেত্রকে বাদ দিয়েছি যা @ সরাইলাইজড এনমেটেশন হিসাবে চিহ্নিত নয় , অর্থাত:

public class Dummy {

    @SerializedName("VisibleValue")
    final String visibleValue;
    final String hiddenValue;

    public Dummy(String visibleValue, String hiddenValue) {
        this.visibleValue = visibleValue;
        this.hiddenValue = hiddenValue;
    }
}


public class SerializedNameOnlyStrategy implements ExclusionStrategy {

    @Override
    public boolean shouldSkipField(FieldAttributes f) {
        return f.getAnnotation(SerializedName.class) == null;
    }

    @Override
    public boolean shouldSkipClass(Class<?> clazz) {
        return false;
    }
}


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

Dummy dummy = new Dummy("I will see this","I will not see this");
String json = gson.toJson(dummy);

এটি ফিরে আসে

Vis "দৃশ্যমান মূল্য": "আমি এটি দেখতে পাব"}


6

আরেকটি পদ্ধতির (বিশেষ করে দরকারী যদি আপনাকে রানটাইমের সময় কোনও ক্ষেত্র বাদ দেওয়ার সিদ্ধান্ত নিতে হয়) হ'ল আপনার জিএসএন দৃষ্টান্তের সাথে টাইপএডাপ্টার নিবন্ধন করা। নীচে উদাহরণ:

Gson gson = new GsonBuilder()
.registerTypeAdapter(BloodPressurePost.class, new BloodPressurePostSerializer())

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

public class BloodPressurePostSerializer implements JsonSerializer<BloodPressurePost> {

    @Override
    public JsonElement serialize(BloodPressurePost src, Type typeOfSrc, JsonSerializationContext context) {
        final JsonObject jsonObject = new JsonObject();

        if (src.systolic > 0) {
            jsonObject.addProperty("systolic", src.systolic);
        }

        if (src.diastolic > 0) {
            jsonObject.addProperty("diastolic", src.diastolic);
        }

        jsonObject.addProperty("units", src.units);

        return jsonObject;
    }
}

6

কোটলিনের টীকাটিও @Transientস্পষ্টতই কৌশলটি করে।

data class Json(
    @field:SerializedName("serialized_field_1") val field1: String,
    @field:SerializedName("serialized_field_2") val field2: String,
    @Transient val field3: String
)

আউটপুট:

{"serialized_field_1":"VALUE1","serialized_field_2":"VALUE2"}

1

আমি কেবল @Exposeটীকাগুলি রেখে কাজ করছি , এখানে আমার ব্যবহার করা আমার সংস্করণ

compile 'com.squareup.retrofit2:retrofit:2.0.2'
compile 'com.squareup.retrofit2:converter-gson:2.0.2'

ইন Modelশ্রেণী:

@Expose
int number;

public class AdapterRestApi {

ইন Adapterশ্রেণী:

public EndPointsApi connectRestApi() {
    OkHttpClient client = new OkHttpClient.Builder()
            .connectTimeout(90000, TimeUnit.SECONDS)
            .readTimeout(90000,TimeUnit.SECONDS).build();

    Retrofit retrofit = new Retrofit.Builder()
            .baseUrl(ConstantRestApi.ROOT_URL)
            .addConverterFactory(GsonConverterFactory.create())
            .client(client)
            .build();

    return retrofit.create  (EndPointsApi.class);
}

1

আমার কাছে কোটলিন সংস্করণ আছে

@Retention(AnnotationRetention.RUNTIME)
@Target(AnnotationTarget.FIELD)
internal annotation class JsonSkip

class SkipFieldsStrategy : ExclusionStrategy {

    override fun shouldSkipClass(clazz: Class<*>): Boolean {
        return false
    }

    override fun shouldSkipField(f: FieldAttributes): Boolean {
        return f.getAnnotation(JsonSkip::class.java) != null
    }
}

এবং কীভাবে আপনি এটি পুনঃনির্মাণ জিএসওএন কনভার্টারফ্যাক্টরিতে যুক্ত করতে পারেন:

val gson = GsonBuilder()
                .setExclusionStrategies(SkipFieldsStrategy())
                //.serializeNulls()
                //.setDateFormat(DateFormat.LONG)
                //.setFieldNamingPolicy(FieldNamingPolicy.UPPER_CAMEL_CASE)
                //.setPrettyPrinting()
                //.registerTypeAdapter(Id.class, IdTypeAdapter())
                .create()
        return GsonConverterFactory.create(gson)

0

এটি আমি সর্বদা ব্যবহার করি:

গসনে প্রয়োগ করা ডিফল্ট আচরণ হ'ল নাল অবজেক্ট ক্ষেত্রগুলি উপেক্ষা করা হয়।

মানে জিসন অবজেক্ট জেএসএনে নাল মান সহ ক্ষেত্রগুলিকে সিরিয়ালাইজ করে না। যদি জাভা অবজেক্টের কোনও ক্ষেত্র শূন্য হয় তবে গসন এটিকে বাদ দেয়।

আপনি এই ফাংশনটি ব্যবহার করতে পারেন কোনও বস্তুকে নাল বা নিজের দ্বারা সেট করা ভাল রূপান্তর করতে

     /**
   * convert object to json
   */
  public String toJson(Object obj) {
    // Convert emtpy string and objects to null so we don't serialze them
    setEmtpyStringsAndObjectsToNull(obj);
    return gson.toJson(obj);
  }

  /**
   * Sets all empty strings and objects (all fields null) including sets to null.
   *
   * @param obj any object
   */
  public void setEmtpyStringsAndObjectsToNull(Object obj) {
    for (Field field : obj.getClass().getDeclaredFields()) {
      field.setAccessible(true);
      try {
        Object fieldObj = field.get(obj);
        if (fieldObj != null) {
          Class fieldType = field.getType();
          if (fieldType.isAssignableFrom(String.class)) {
            if(fieldObj.equals("")) {
              field.set(obj, null);
            }
          } else if (fieldType.isAssignableFrom(Set.class)) {
            for (Object item : (Set) fieldObj) {
              setEmtpyStringsAndObjectsToNull(item);
            }
            boolean setFielToNull = true;
            for (Object item : (Set) field.get(obj)) {
              if(item != null) {
                setFielToNull = false;
                break;
              }
            }
            if(setFielToNull) {
              setFieldToNull(obj, field);
            }
          } else if (!isPrimitiveOrWrapper(fieldType)) {
            setEmtpyStringsAndObjectsToNull(fieldObj);
            boolean setFielToNull = true;
            for (Field f : fieldObj.getClass().getDeclaredFields()) {
              f.setAccessible(true);
              if(f.get(fieldObj) != null) {
                setFielToNull = false;
                break;
              }
            }
            if(setFielToNull) {
              setFieldToNull(obj, field);
            }
          }
        }
      } catch (IllegalAccessException e) {
        System.err.println("Error while setting empty string or object to null: " + e.getMessage());
      }
    }
  }

  private void setFieldToNull(Object obj, Field field) throws IllegalAccessException {
    if(!Modifier.isFinal(field.getModifiers())) {
      field.set(obj, null);
    }
  }

  private boolean isPrimitiveOrWrapper(Class fieldType)  {
    return fieldType.isPrimitive()
        || fieldType.isAssignableFrom(Integer.class)
        || fieldType.isAssignableFrom(Boolean.class)
        || fieldType.isAssignableFrom(Byte.class)
        || fieldType.isAssignableFrom(Character.class)
        || fieldType.isAssignableFrom(Float.class)
        || fieldType.isAssignableFrom(Long.class)
        || fieldType.isAssignableFrom(Double.class)
        || fieldType.isAssignableFrom(Short.class);
  }
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.