স্প্রিং বুটে প্রতিক্রিয়া হিসাবে JSON অবজেক্ট ফিরিয়ে দেওয়া


88

স্প্রিং বুটে আমার একটি নমুনা রেস্টকন্ট্রোলার রয়েছে:

@RestController
@RequestMapping("/api")
class MyRestController
{
    @GetMapping(path = "/hello")
    public JSONObject sayHello()
    {
        return new JSONObject("{'aa':'bb'}");
    }
}

আমি জেএসএন লাইব্রেরি ব্যবহার করছি org.json

আমি যখন এপিআই হিট করি তখন আমি এই /helloব্যতিক্রমটি পাই:

Servlet.service () সার্লেটের জন্য [প্রেরণকারী সার্ভালেট] পথের প্রসঙ্গে [] ব্যতিক্রম ছুঁড়ে ফেলেছে [অনুরোধ প্রক্রিয়াকরণ ব্যর্থ হয়েছে; নেস্টেড ব্যতিক্রম java.lang.IllegalArgumentException: প্রকারের মূল্যের জন্য কোনও রূপান্তরকারী পাওয়া যায় নি: শ্রেণি org.json.JSONObject] মূল কারণ সহ

java.lang.IllegalArgumentException: প্রকারের রিটার্ন মানের জন্য কোনও রূপান্তরকারী পাওয়া যায় নি: শ্রেণি org.json.JSONObject

সমস্যা কি? কেউ কি ঠিক কী ঘটছে তা ব্যাখ্যা করতে পারেন?


জ্যাকসন জেএসএনওজেক্টকে জসন-এ রূপান্তর করতে পারে না।
পাউ

ঠিক আছে, আমি বুঝতে পারি। এটি ঠিক করার জন্য কী করা যেতে পারে?
iwekesi

4
আমি প্রতিক্রিয়া উড়তে নির্মিত হবে। আমি প্রতিটি প্রতিক্রিয়ার জন্য নির্দিষ্ট ক্লাস তৈরি করতে চাই না।
iwekesi

4
আপনার পদ্ধতিটি স্ট্রিং হিসাবে ফিরে আসা ভাল better অতিরিক্ত হিসাবে, আপনি এই পদ্ধতিতে টেক্সট @ রেসপন্সবডিও যুক্ত করতে পারেন, এটি অনুরোধ অনুসারে আপনার প্রতিক্রিয়াটি পরিচালনা করবে :-)@GetMapping(path = "/hello") @ResponseBody public String sayHello() {return"{'aa':'bb'}";}
Vegaasen

@ ওয়েগাসেন আপনি রেসপন্সবডি সম্পর্কে কিছুটা ব্যাখ্যা করতে পারেন
আইবেক্সি

উত্তর:


109

আপনি যেমন স্প্রিং বুট ওয়েব ব্যবহার করছেন, জ্যাকসন নির্ভরতা অন্তর্নিহিত এবং আমাদের স্পষ্টভাবে সংজ্ঞায়িত করতে হবে না। আপনি pom.xmlযদি গ্রহনটি ব্যবহার করেন তবে নির্ভরতা শ্রেণিবিন্যাস ট্যাবে আপনার জ্যাকসন নির্ভরতার জন্য পরীক্ষা করতে পারেন।

এবং আপনি যেমন হিসাবে মন্তব্য করেছেন @RestControllerসেখানে সুস্পষ্ট জেসন রূপান্তর করার দরকার নেই। কেবলমাত্র একটি POJO ফিরিয়ে দিন এবং জ্যাকসন সিরিয়ালাইজার জসসনে রূপান্তর করার যত্ন নেবে। @ResponseBody@ কন্ট্রোলারের সাথে ব্যবহার করার সময় এটি ব্যবহারের সমতুল্য । বরং স্থাপন চেয়ে @ResponseBodyযে নিয়ামক পদ্ধতির উপর আমরা স্থান @RestControllerভ্যানিলা পরিবর্তে @Controllerএবং @ResponseBodyডিফল্টরূপে যে নিয়ামক সমস্ত সম্পদের উপর প্রয়োগ করা হয়।
এই লিঙ্কটিটি দেখুন: https://docs.spring.io/spring/docs/current/spring-framework-references/html/mvc.html#mvc-ann-responsebodybody

আপনি যে সমস্যার মুখোমুখি হচ্ছেন তা হ'ল প্রত্যাবর্তিত অবজেক্টের (জেএসএনওবজেক্ট) নির্দিষ্ট বৈশিষ্ট্যের জন্য গেটর নেই। এবং আপনার উদ্দেশ্য এই JSONObject সিরিয়ালাইজ করার নয়, বরং কোনও POJO সিরিয়ালাইজ করার জন্য। সুতরাং শুধু POJO ফিরিয়ে দিন।
এই লিঙ্কটি দেখুন: https://stackoverflow.com/a/35822500/5039001

আপনি যদি কোনও জসন সিরিয়ালযুক্ত স্ট্রিংটি ফিরে আসতে চান তবে কেবল স্ট্রিংটি ফিরিয়ে দিন। স্প্রিং এই ক্ষেত্রে জেএসএন কনভার্টারের পরিবর্তে স্ট্রিংএইচটিপিএমেসেজ কনভার্টার ব্যবহার করবে।


যদি জাসন স্ট্রিংটি আপনি জাভা থেকে ফিরে আসতে চান তবে আপনি যদি ইতিমধ্যে জেসন সিরিয়ালযুক্ত হন তবে আপনি কেবল একটি স্ট্রিং ফিরিয়ে দিতে পারেন। স্ট্রিংটিকে জসন এবং জসনকে আবার স্ট্রিংয়ে রূপান্তর করতে হবে না।
প্রিম কুমার

6
আপনি যদি অনমনীয় সংকলন-সময় কাঠামো ছাড়াই নাম-মান জোড়ার সেটটি ফেরত করতে চান তবে আপনি কোনও Map<String,Object>বা কোনও Propertiesজিনিস ফেরত দিতে পারেন
Vihung

@প্রিম কুমার এলোমেলো প্রশ্ন: 'ভ্যানিলা কন্ট্রোলার এবং রেসপন্সবডি'র পরিবর্তে আপনার অর্থ কী? এখানে কি ভ্যানিলা?
অর্কুন ওজেন

আমি একটি নিয়ামক বলতে চাইছিলাম এবং প্রতিটি অনুরোধ পদ্ধতিতে রেসপন্সবডি টীকা দিয়েছি।
প্রিম কুমার

68

আপনার বর্তমান পদ্ধতির কাজ না করার কারণটি হ'ল জ্যাকসন ডিফল্টরূপে সিরিয়ালাইজ করতে এবং অবজেক্টগুলি ডিেসরিয়াল করতে ব্যবহৃত হয়। তবে এটি কীভাবে সিরিয়ালিয়াল করবেন তা জানে না JSONObject। আপনি যদি একটি গতিশীল JSON কাঠামো তৈরি করতে চান তবে আপনি একটি ব্যবহার করতে পারেন Map, উদাহরণস্বরূপ:

@GetMapping
public Map<String, String> sayHello() {
    HashMap<String, String> map = new HashMap<>();
    map.put("key", "value");
    map.put("foo", "bar");
    map.put("aa", "bb");
    return map;
}

এটি নিম্নলিখিত JSON প্রতিক্রিয়া বাড়ে:

{ "key": "value", "foo": "bar", "aa": "bb" }

এটি কিছুটা সীমাবদ্ধ, যেহেতু শিশুদের অবজেক্ট যুক্ত করা কিছুটা বেশি কঠিন হয়ে উঠতে পারে। জ্যাকসন ব্যবহার যদিও এর নিজস্ব প্রক্রিয়া আছে, ObjectNodeএবং ArrayNode। এটি ব্যবহার করতে, ObjectMapperআপনার পরিষেবা / নিয়ামকটিতে আপনাকে অটোয়ার করতে হবে । তারপরে আপনি ব্যবহার করতে পারেন:

@GetMapping
public ObjectNode sayHello() {
    ObjectNode objectNode = mapper.createObjectNode();
    objectNode.put("key", "value");
    objectNode.put("foo", "bar");
    objectNode.put("number", 42);
    return objectNode;
}

এই পদ্ধতির সাহায্যে আপনি শিশুদের অবজেক্টস, অ্যারে যুক্ত করতে এবং বিভিন্ন ধরণের ব্যবহার করতে পারবেন।


4
এখানে ম্যাপার কি?
iwekesi

4
@ আইভেক্সি হ'ল জ্যাকসনকে ObjectMapperআপনার স্বীকৃতি দেওয়া উচিত (আমার শেষ কোড স্নিপেটের উপরের অনুচ্ছেদটি দেখুন)।
g00glen00b

4
এটি অবাক করে জানা যায় যে অর্থবহ জেএসওএন অবজেক্ট তৈরি করতে একজনকে এ জাতীয় দৈর্ঘ্য যেতে হবে! এছাড়া দু: খিত যে চরম করে তোলে কোন সমস্ত (এ প্রচেষ্টা spring.io/guides/gs/actuator-service ) এই সীমাবদ্ধতা কল আউট। ভাগ্যক্রমে, আমাদেরও আছে! ;)
কোজিটোয়ারগোসাম

@ হিকারুশিন্দো java.util.HashMapজাভা 1.2 এর পর থেকে জাভার মূল কার্যকারিতা।
g00glen00b

44

আপনি হয় String@ ভিগাসেনের পরামর্শ অনুসারে প্রতিক্রিয়া ফিরিয়ে দিতে পারেন বা আপনি ResponseEntityনীচে হিসাবে স্প্রিংয়ের সরবরাহিত অবজেক্টটি ব্যবহার করতে পারেন । এই উপায় দ্বারা আপনি ফিরে আসতে পারেন Http status codeযা ওয়েব সার্ভিস কলটিতে আরও সহায়ক।

@RestController
@RequestMapping("/api")
public class MyRestController
{

    @GetMapping(path = "/hello", produces=MediaType.APPLICATION_JSON_VALUE)
    public ResponseEntity<Object> sayHello()
    {
         //Get data from service layer into entityList.

        List<JSONObject> entities = new ArrayList<JSONObject>();
        for (Entity n : entityList) {
            JSONObject entity = new JSONObject();
            entity.put("aa", "bb");
            entities.add(entity);
        }
        return new ResponseEntity<Object>(entities, HttpStatus.OK);
    }
}

4
যদি আমি সত্তাগুলিতে JSONObject যুক্ত করি তবে এটি আবার আমাকে অনুরূপ ব্যতিক্রম দিচ্ছে
iwekesi

@ সঙ্গম আপনার উত্তর আমাকে জ্যাকসন-ডেটাফর্ম্যাট-এক্সএমএল সম্পর্কিত আরও একটি সমস্যার জন্য সহায়তা করেছে
divineমানের

এটি ছিল একটি বড় সাহায্য! ধন্যবাদ!
জোন্স-ক্রিস

4
আমি উত্তর দিচ্ছি কেন এই উত্তরটি আরও বেশি উত্সাহিত হয় নি। আমি স্প্রিং-এও নতুন, তাই আমি জানি না এটি একটি ভাল সফটওয়্যার ইঞ্জিনিয়ারিং অনুশীলন কিনা। এই বলে যে, এই উত্তর আমাকে সত্যিই সাহায্য করেছে। তবে, এ নিয়ে আমার অনেক সমস্যা হয়েছিল JSONObject, তবে যেহেতু স্প্রিং জ্যাকসন ব্যবহার করে আমি এটিকে HashMapপরিবর্তে পরিবর্তিত করেছিলাম এবং তারপরে এই উত্তরটিতে যে কোডটি পড়েছি তা কার্যকর হয়েছে।
মেলভিন রোস্ট

4
মিডিয়া টাইপ পরামর্শ দেওয়ার জন্য +1. APPLICATION_JSON_VALUE যেহেতু এটি নিশ্চিত করে যে উত্পাদিত ফলাফলটি যদি আপনি সংজ্ঞায়িত না করেন তবে এক্সএমএল হিসাবে জসন হিসাবে পার্স করা হবে
সন্দীপ মান্দোরি

11

আপনি এটির জন্য একটি হ্যাশম্যাপও ব্যবহার করতে পারেন

@GetMapping
public HashMap<String, Object> get() {
    HashMap<String, Object> map = new HashMap<>();
    map.put("key1", "value1");
    map.put("results", somePOJO);
    return map;
}

6
@RequestMapping("/api/status")
public Map doSomething()
{
    return Collections.singletonMap("status", myService.doSomething());
}

পুনশ্চ. শুধুমাত্র 1 টি মানের জন্য কাজ করে


3

ব্যবহার ResponseEntity<ResponseBean>

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

@GetMapping(path = "/login")
public ResponseEntity<ServiceStatus> restApiExample(HttpServletRequest request,
            HttpServletResponse response) {
        String username = request.getParameter("username");
        String password = request.getParameter("password");

        loginService.login(username, password, request);
        return new ResponseEntity<ServiceStatus>(ServiceStatus.LOGIN_SUCCESS,
                HttpStatus.ACCEPTED);
    }

প্রতিক্রিয়া সার্ভিস স্ট্যাটাস বা (রেসপন্সবডি) এর জন্য

    public enum ServiceStatus {

    LOGIN_SUCCESS(0, "Login success"),

    private final int id;
    private final String message;

    //Enum constructor
    ServiceStatus(int id, String message) {
        this.id = id;
        this.message = message;
    }

    public int getId() {
        return id;
    }

    public String getMessage() {
        return message;
    }
}

প্রতিক্রিয়া হিসাবে স্প্রিং REST এপিআই এর নীচের কী থাকা উচিত

  1. স্থিতি কোড
  2. বার্তা

আপনি নীচে চূড়ান্ত প্রতিক্রিয়া পাবেন

{

   "StatusCode" : "0",

   "Message":"Login success"

}

আপনি আপনার প্রয়োজন অনুসারে রেসপন্সবডি (জাভা পোজো, এনইউএম ইত্যাদি) ব্যবহার করতে পারেন।


2

আরও সঠিকভাবে এপিআই ক্যোয়ারির জন্য ডিটিও তৈরি করুন, উদাহরণস্বরূপ এনটিটিডিটিও:

  1. সত্তার তালিকা সহ ডিফল্ট প্রতিক্রিয়া ঠিক আছে:
@GetMapping(produces=MediaType.APPLICATION_JSON_VALUE)
@ResponseStatus(HttpStatus.OK)
public List<EntityDto> getAll() {
    return entityService.getAllEntities();
}

তবে আপনার যদি বিভিন্ন মানচিত্রের প্যারামিটারগুলি দরকার হয় তবে আপনি পরবর্তী দুটি উদাহরণ ব্যবহার করতে পারেন
return. মানচিত্রের মতো একটি পরামিতি ফেরতের জন্য:

@GetMapping(produces=MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<Object> getOneParameterMap() {
    return ResponseEntity.status(HttpStatus.CREATED).body(
            Collections.singletonMap("key", "value"));
}
  1. এবং যদি আপনার কিছু প্যারামিটারের ফেরত মানচিত্রের প্রয়োজন হয় (জাভা 9 থেকে):
@GetMapping(produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<Object> getSomeParameters() {
    return ResponseEntity.status(HttpStatus.OK).body(Map.of(
            "key-1", "value-1",
            "key-2", "value-2",
            "key-3", "value-3"));
}

1

আপনার যদি স্ট্রিং ব্যবহার করে কোনও JSON অবজেক্ট ফেরত আসতে হয়, তবে নীচেরগুলিতে কাজ করা উচিত:

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.http.ResponseEntity;
...

@RestController
@RequestMapping("/student")
public class StudentController {

    @GetMapping
    @RequestMapping("/")
    public ResponseEntity<JsonNode> get() throws JsonProcessingException {
        ObjectMapper mapper = new ObjectMapper();
        JsonNode json = mapper.readTree("{\"id\": \"132\", \"name\": \"Alice\"}");
        return ResponseEntity.ok(json);
    }
    ...
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.