জ্যাকসন এবং জেনেরিক ধরণের রেফারেন্স


107

আমি জেনিকন পদ্ধতির জন্য জ্যাকসন জসন লাইব্রেরিটি নিম্নরূপে ব্যবহার করতে চাই:

public MyRequest<T> tester() {
    TypeReference<MyWrapper<T>> typeRef = new TypeReference<MyWrapper<T>>();  
    MyWrapper<T> requestWrapper = (MyWrapper<T>) JsonConverter.fromJson(jsonRequest, typeRef);
    return requestWrapper.getRequest();
}

...

public class MyWrapper<T> {

    private MyRequest<T> request;

    public MyRequest<T> getRequest() {
        return request;
    }

    public void setRequest(MyRequest<T> request) {
        this.request = request;
    }
}


 public class MyRequest{
     private List<T> myobjects;

     public void setMyObjects(List<T> ets) {
         this.myobjects = ets;
     }

     @NotNull
     @JsonIgnore
     public T getMyObject() {
         return myobjects.get(0);
     }
}

এখন সমস্যাটি হ'ল আমি যখন getMyObject () কল করি যা অনুরোধের অভ্যন্তরে থাকে জ্যাকসন নেস্টেড কাস্টম অবজেক্টটিকে একটি লিঙ্কডহ্যাশম্যাপ হিসাবে ফিরিয়ে দেয়। এমন কোনও উপায় আছে যেখানে আমি উল্লেখ করেছি যে টি অবজেক্টটি ফেরত দেওয়া দরকার ?. উদাহরণস্বরূপ: আমি যদি গ্রাহক প্রকারের অবজেক্টটি প্রেরণ করি তবে গ্রাহককে সেই তালিকা থেকে ফিরে আসা উচিত?

ধন্যবাদ।


দয়া করে getT ()
জিম গ্যারিসন

এই প্রশ্নের অনুরূপ stackoverflow.com/questions/6062011/... কিন্তু তারা TypeFactory ব্যবহার প্রকার উল্লেখ পরামর্শ দিয়েছেন। তবে সংকলনের সময়টি আমি জানি না ...
টেকজেন

টাইপফ্যাক্টির এমন পদ্ধতি রয়েছে যা স্থির শ্রেণীর প্রয়োজন হয় না; ক্রয়কলেশন টাইপ এবং অন্যান্য।
স্টেক্সম্যান 22

সম্পূর্ণ কোড ভাগ করুন। আমিও একই সমস্যায় পড়ছি।
এজেড_

TypeReferenceবিমূর্ত নয় ?
কাইল ডেলানি

উত্তর:


194

এটি জাভা টাইপ ইরেজরের সাথে একটি সুপরিচিত সমস্যা: টি হ'ল একটি টাইপ ভেরিয়েবল এবং আপনার অবশ্যই প্রকৃত ক্লাসটি নির্দেশ করতে হবে, সাধারণত শ্রেণি যুক্তি হিসাবে। এই জাতীয় তথ্য ছাড়াই, সীমাবদ্ধতা ব্যবহার করা ভাল যা করা যায়; এবং প্লেইন টি 'টি প্রসারিত অবজেক্ট' এর মতো প্রায় একই। এবং জ্যাকসন তারপরে JSON অবজেক্টসকে মানচিত্র হিসাবে আবদ্ধ করবে।

এই ক্ষেত্রে, পরীক্ষক পদ্ধতির ক্লাসে অ্যাক্সেস থাকা দরকার এবং আপনি এটি তৈরি করতে পারেন

JavaType type = mapper.getTypeFactory().
  constructCollectionType(List.class, Foo.class)

এবং তারপর

List<Foo> list = mapper.readValue(new File("input.json"), type);

16
এটি কাজ করে: আমি নিম্নলিখিতগুলি করেছি: জাভাটাইপ টপমোস্ট = ম্যাপার.জেটটাইপফ্যাক্ট্রি () const এবং তারপরে রিডভ্যালুটি করেছে এবং শেষ পর্যন্ত এটি কাজ করেছে :)
টেকজেন

হ্যাঁ, এটি কাজ করে - মানচিত্র / সংগ্রহের ধরণ বাদে জেনেরিক টাইপ তৈরির পদ্ধতিটি নির্দেশ করার জন্য ধন্যবাদ!
স্টেক্সম্যান

1
@ স্ট্যাকসম্যান এখন থেকে এই ধরণের জিনিসগুলির জন্য ক্লাসমেট ব্যবহার করা কি ভাল?
হুশায়েট

2
@ হ্যাঁ হ্যাঁ, প্রযুক্তিগতভাবে জাভা-সহপাঠী লিবিব উন্নত। তবে জ্যাকসনের সাথে এটি সংহত করা কিছুটা জটিল কারণ জ্যাকসনের নিজস্ব ধরণের বিমূর্তি এপিআইয়ের একীভূত অংশ। দীর্ঘমেয়াদে জ্যাকসনকে এম্বেড করা বা ডিপ মাধ্যমে ক্লাসমেট কোড ব্যবহারের উপযুক্ত উপায় বের করা ভাল।
স্টেক্সম্যান

1
আমার মনে হয় জ্যাকসনের জেনেরিকের ফাঁকফোকরগুলির মতো বিষয়টি কভার করা উচিত নয়, তবে যেভাবেই হোক না কেন, এটি খুব ভালভাবে সম্পাদন করে।
অ্যাড্রিয়ান বাকের

6

'জাভাটাইপ' কাজ করে !! আমি জসন স্ট্রিং টু অ্যারেলিস্ট জাভা অবজেক্টগুলিতে একটি তালিকা আনমসারল (ডিসরিয়ালাইজেশন) করার চেষ্টা করছিলাম এবং বেশ কয়েকদিন থেকেই সমাধানের জন্য লড়াই করে যাচ্ছিলাম।
নীচে কোডগুলি যা শেষ পর্যন্ত আমাকে সমাধান দিয়েছে is কোড:

JsonMarshallerUnmarshaller<T> {
    T targetClass;

    public ArrayList<T> unmarshal(String jsonString) {
        ObjectMapper mapper = new ObjectMapper();

        AnnotationIntrospector introspector = new JacksonAnnotationIntrospector();
        mapper.getDeserializationConfig()
            .withAnnotationIntrospector(introspector);

        mapper.getSerializationConfig()
            .withAnnotationIntrospector(introspector);
        JavaType type = mapper.getTypeFactory().
            constructCollectionType(
                ArrayList.class, 
                targetclass.getClass());

        try {
            Class c1 = this.targetclass.getClass();
            Class c2 = this.targetclass1.getClass();
            ArrayList<T> temp = (ArrayList<T>) 
                mapper.readValue(jsonString,  type);
            return temp ;
        } catch (JsonParseException e) {
            e.printStackTrace();
        } catch (JsonMappingException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return null ;
    }  
}

টার্গেটক্লাস কীভাবে শুরু করবেন?
এজেড_

দয়া করে আমাকে একটি ছোট উদাহরণ দেখান। আমি ক্লাস <?> টার্গেট পাস করছি এবং তারপরে টার্গেটটি পেয়েছি lassgetClassName ()।
এজেড_

1
নিম্নলিখিত হিসাবে কোনও কনস্ট্রাক্টর যুক্ত করুন: জসনমারশালারউনমারশালার <টি> {প্রাইভেট ক্লাস <টি> টার্গেটক্লাস; জসনমারশালারউনমারশালার (ক্লাস <টি> সি) {টার্গেটক্লাস = সি; Class everywhere সর্বত্র কোথাও getClass না করে এই শ্রেণিটি ব্যবহার করার জন্য 'unmarshal' ফাংশনে এখনই যথাযথ পরিবর্তন করুন।
রশিদশাই 1

কয়েকটি নোট: কোডটি সমস্ত ব্যতিক্রম IOException(কেবলমাত্র একটি ক্যাচ প্রয়োজন) এর সাব-টাইপ , এবং ডিফল্ট টীকাগুলি ইন্ট্রোস্পেক্টর ইতিমধ্যে রয়েছে তা উল্লেখ করে অনেকটা সরল করা যায় JacksonAnnotationIntrospector- সুতরাং এর জন্য কিছু করার দরকার নেই ObjectMapper, কেবল এটি নির্মাণ করুন এবং এটি কাজ করে।
স্টেক্সম্যান

সুতরাং এই কোড আমি সংকলন পেতে না। পরিবর্তে পেস্ট করার জন্য কোনও লাইভ উদাহরণ পেয়েছেন?
রেঞ্চ

0

আমি একটি কাজের উদাহরণ অন্তর্ভুক্ত করতে রাশিডাইসাই 1 এর উত্তরটি পরিবর্তন করেছি

JsonMarshaller.java

import java.io.*;
import java.util.*;

public class JsonMarshaller<T> {
    private static ClassLoader loader = JsonMarshaller.class.getClassLoader();

    public static void main(String[] args) {
        try {
            JsonMarshallerUnmarshaller<Station> marshaller = new JsonMarshallerUnmarshaller<>(Station.class);
            String jsonString = read(loader.getResourceAsStream("data.json"));
            List<Station> stations = marshaller.unmarshal(jsonString);
            stations.forEach(System.out::println);
            System.out.println(marshaller.marshal(stations));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @SuppressWarnings("resource")
    public static String read(InputStream ios) {
        return new Scanner(ios).useDelimiter("\\A").next(); // Read the entire file
    }
}

আউটপুট

Station [id=123, title=my title, name=my name]
Station [id=456, title=my title 2, name=my name 2]
[{"id":123,"title":"my title","name":"my name"},{"id":456,"title":"my title 2","name":"my name 2"}]

JsonMarshallerUnmarshaller.java

import java.io.*;
import java.util.List;

import com.fasterxml.jackson.core.*;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector;

public class JsonMarshallerUnmarshaller<T> {
    private ObjectMapper mapper;
    private Class<T> targetClass;

    public JsonMarshallerUnmarshaller(Class<T> targetClass) {
        AnnotationIntrospector introspector = new JacksonAnnotationIntrospector();

        mapper = new ObjectMapper();
        mapper.getDeserializationConfig().with(introspector);
        mapper.getSerializationConfig().with(introspector);

        this.targetClass = targetClass;
    }

    public List<T> unmarshal(String jsonString) throws JsonParseException, JsonMappingException, IOException {
        return parseList(jsonString, mapper, targetClass);
    }

    public String marshal(List<T> list) throws JsonProcessingException {
        return mapper.writeValueAsString(list);
    }

    public static <E> List<E> parseList(String str, ObjectMapper mapper, Class<E> clazz)
            throws JsonParseException, JsonMappingException, IOException {
        return mapper.readValue(str, listType(mapper, clazz));
    }

    public static <E> List<E> parseList(InputStream is, ObjectMapper mapper, Class<E> clazz)
            throws JsonParseException, JsonMappingException, IOException {
        return mapper.readValue(is, listType(mapper, clazz));
    }

    public static <E> JavaType listType(ObjectMapper mapper, Class<E> clazz) {
        return mapper.getTypeFactory().constructCollectionType(List.class, clazz);
    }
}

Station.java

public class Station {
    private long id;
    private String title;
    private String name;

    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return String.format("Station [id=%s, title=%s, name=%s]", id, title, name);
    }
}

data.json

[{
  "id": 123,
  "title": "my title",
  "name": "my name"
}, {
  "id": 456,
  "title": "my title 2",
  "name": "my name 2"
}]
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.