স্প্রিং এমভিসি - কীভাবে রেস্ট কন্ট্রোলারে জেএসএন হিসাবে সরল স্ট্রিংটি ফিরবেন


137

আমার প্রশ্নটি মূলত এই প্রশ্নের অনুসরণীয় ।

@RestController
public class TestController
{
    @RequestMapping("/getString")
    public String getString()
    {
        return "Hello World";
    }
}

উপরের দিকে, স্প্রিং প্রতিক্রিয়া বডিতে "হ্যালো ওয়ার্ল্ড" যুক্ত করবে। আমি কীভাবে কোনও JSON প্রতিক্রিয়া হিসাবে একটি স্ট্রিং ফিরিয়ে দিতে পারি? আমি বুঝতে পারি যে আমি উদ্ধৃতিগুলি যোগ করতে পারি, তবে এটি হ্যাকের মতো মনে হয়।

এই ধারণাটি ব্যাখ্যা করতে দয়া করে কোনও উদাহরণ সরবরাহ করুন।

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


আপনি মানচিত্র বা আপনার স্ট্রিং ধারণ করে এমন কোনও অবজেক্ট / সত্তা ফিরিয়ে দিতে পারবেন
ডেনিস ডেনিসুক

সুতরাং আপনি কী বোঝাতে চেয়েছেন যে স্ট্রিং মানটি কোনও JSON স্ট্রিংয়ে সিরিয়ালযুক্ত করা উচিত?
সোটিরিওস ডেলিমনোলিস

উত্তর:


150

হয় রিটার্ন করুন text/plain( স্প্রিং এমভিসি 3 কন্ট্রোলার থেকে কেবল স্ট্রিং মেসেজ হিসাবে রিটার্ন হিসাবে ) বা আপনার স্ট্রিংকে মোড়ানো কোনও বিষয়

public class StringResponse {

    private String response;

    public StringResponse(String s) { 
       this.response = s;
    }

    // get/set omitted...
}


আপনার প্রতিক্রিয়া প্রকারটি MediaType.APPLICATION_JSON_VALUE(= "application/json") এ সেট করুন

@RequestMapping(value = "/getString", method = RequestMethod.GET,
                produces = MediaType.APPLICATION_JSON_VALUE)

এবং আপনার মতো দেখতে একটি জেএসওএন পাবেন

{  "response" : "your string value" }

124
আপনি Collections.singletonMap("response", "your string value")একটি মোড়কের ক্লাস না তৈরি করে একই ফলাফল অর্জন করতে ফিরে আসতে পারেন।
বোহস্লভ বুর্গহার্ট

@ বোহস্লাভ এটি দুর্দান্ত টিপ।
শান

6
এটি সত্য নয় যে এর জন্য একটি কী এবং একটি মান প্রয়োজন। একটি একক স্ট্রিং বা স্ট্রিংগুলির একটি অ্যারে উভয়ই বৈধ JSON। যদি আপনি দ্বিমত পোষণ করেন তবে আপনি ব্যাখ্যা করতে পারেন কেন জসনলিন্ট ওয়েবসাইটগুলি উভয়কেই বৈধ জেএসএন হিসাবে গ্রহণ করে।
কাইলএম

2
মোড়কের ক্লাসটি কীভাবে জেএসএনে রূপান্তরিত হয়?
রকি ইন্ডি

3
আমি মনে করি এটি ফিরে আসার পক্ষে যথেষ্টCollections.singleton("your string value")
গৌই

54

জেএসএন মূলত পিএইচপি বা জাভা প্রসঙ্গে স্ট্রিং। এর অর্থ হল যে স্ট্রিং যা বৈধ JSON, প্রতিক্রিয়াতে ফিরে আসতে পারে। নিম্নলিখিত কাজ করা উচিত।

  @RequestMapping(value="/user/addUser", method=RequestMethod.POST)
  @ResponseBody
  public String addUser(@ModelAttribute("user") User user) {

    if (user != null) {
      logger.info("Inside addIssuer, adding: " + user.toString());
    } else {
      logger.info("Inside addIssuer...");
    }
    users.put(user.getUsername(), user);
    return "{\"success\":1}";
  }

এটি সাধারণ স্ট্রিং প্রতিক্রিয়া জন্য ঠিক আছে। তবে জটিল জেএসওএন প্রতিক্রিয়ার জন্য শন বর্ণিত আপনার মোড়ক ক্লাস ব্যবহার করা উচিত।


7
এটি উত্তর গ্রহণ করা উচিত, কারণ এটি ওপি-র প্রশ্নের সঠিক উত্তর ছিল।
এসআরআই

ধন্যবাদ, @ রেসপন্সবডি আমার যা প্রয়োজন তা ছিল
ঝুঁকিপূর্ণ

কৌতূহল যে পাবলিক কীওয়ার্ডের আগে বা পরে @ রেসপন্সবডিটির জন্য "আরও ভাল" অবস্থান? আমি সর্বদা এটির পরে রেখেছি, যেহেতু এটি ফেরতের মানের সাথে আরও বেশি চিহ্নিত।
ডেভিড ব্র্যাডলি

26

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

ব্যবহারের উদাহরণ:

@RestController
public class TestController
{
    @RequestMapping("/getString")
    public String getString()
    {
        return JSONObject.quote("Hello World");
    }
}

1
হতে পারে আপনার উত্তরে আপনার উল্লেখ করা উচিত, এটি "\"Hello World\""ঠিক একইভাবে কাজ করবে ডাব্লু / ও অতিরিক্ত নির্ভরশীল - এটি ঠিক কি JSONObject.quote()করে?
জেরিকো

আমি সমাধানটি পছন্দ করি না, তবে এটি আমার পক্ষে কাজ করে। :-)
মাইকেল হেগনার

22

আপনি নীচে হিসাবে সহজে সম্পত্তি JSONসঙ্গে ফিরে আসতে পারেনStringresponse

@RestController
public class TestController {
    @RequestMapping(value = "/getString", produces = MediaType.APPLICATION_JSON_VALUE)
    public Map getString() {
        return Collections.singletonMap("response", "Hello World");
    }
}

2
আপনি যখনই '@ রিস্টকন্ট্রোলার' ব্যবহার করেন তখন আপনাকে '@ রেসপন্সবডি' ব্যবহার করতে হবে না
জিতেন্দ্র ভার্শনে

12

কেবলমাত্র ডিফল্ট StringHttpMessageConverterউদাহরণটি নিবন্ধন করুন :

@Configuration
public class WebMvcConfiguration extends WebMvcConfigurationSupport {
  /**
   * Unregister the default {@link StringHttpMessageConverter} as we want Strings
   * to be handled by the JSON converter.
   *
   * @param converters List of already configured converters
   * @see WebMvcConfigurationSupport#addDefaultHttpMessageConverters(List)
   */
  @Override
  protected void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
    converters.stream()
      .filter(c -> c instanceof StringHttpMessageConverter)
      .findFirst().ifPresent(converters::remove);
  }
}

উভয় নিয়ামক অ্যাকশন হ্যান্ডলার পদ্ধতি এবং নিয়ামক ব্যতিক্রম হ্যান্ডলারগুলির সাথে পরীক্ষিত:

@RequestMapping("/foo")
public String produceFoo() {
  return "foo";
}

@ExceptionHandler(FooApiException.class)
public String fooException(HttpServletRequest request, Throwable e) {
  return e.getMessage();
}

চূড়ান্ত নোট:

  • extendMessageConvertersস্প্রিং ৪.১.৩ থেকে পাওয়া যায়, যদি পূর্ববর্তী সংস্করণে চলতে থাকে তবে আপনি একই কৌশলটি ব্যবহার করে প্রয়োগ করতে পারেন configureMessageConverters, এটি কিছুটা বেশি কাজ নেয়।
  • এটি অন্যান্য অনেকগুলি সম্ভাব্য পদ্ধতির একটি পদ্ধতির ছিল, যদি আপনার অ্যাপ্লিকেশনটি কেবল JSON এবং অন্য কোনও সামগ্রীর ধরণ না দেয় তবে আপনি ডিফল্ট রূপান্তরকারীদের এড়িয়ে যাওয়া এবং একক জ্যাকসন রূপান্তরকারী যুক্ত করা ভাল। আর একটি পদ্ধতি হ'ল ডিফল্ট রূপান্তরকারীগুলিকে যুক্ত করা কিন্তু বিভিন্ন ক্রমে যাতে জ্যাকসন রূপান্তরকারীটি স্ট্রিংয়ের আগে থাকে। এটি নিয়ন্ত্রক অ্যাকশন পদ্ধতিগুলিকে এই নির্দেশ দিতে দেয় যে তারা কীভাবে প্রতিক্রিয়ার মিডিয়া ধরণের উপর নির্ভর করে স্ট্রিংকে রূপান্তর করতে চায়।

1
আপনার 2 য় চূড়ান্ত নোট সম্পর্কিত একটি উদাহরণ কোড পেয়ে ভাল লাগবে।
টনি বাগুয়েট

1
converters.removeIf(c -> c instanceof StringHttpMessageConverter)
ক্রাইলিস -কোটিরিওপটিস্টিস্টিক-

10

আমি জানি যে এই প্রশ্নটি পুরানো তবে আমিও এতে অবদান রাখতে চাই:

অন্যের প্রতিক্রিয়ার মধ্যে প্রধান পার্থক্য হ্যাশম্যাপ রিটার্ন।

@GetMapping("...")
@ResponseBody
public Map<String, Object> endPointExample(...) {

    Map<String, Object> rtn = new LinkedHashMap<>();

    rtn.put("pic", image);
    rtn.put("potato", "King Potato");

    return rtn;

}

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

{"pic":"a17fefab83517fb...beb8ac5a2ae8f0449","potato":"King Potato"}

2
কেন আপনি পদ্ধতিটিকে হ্যাশম্যাপ ফেরত হিসাবে ঘোষণা করছেন? এলএইচএম মানচিত্র প্রয়োগ করে।
JL_SO

6

সহজ করুন:

    @GetMapping("/health")
    public ResponseEntity<String> healthCheck() {
        LOG.info("REST request health check");
        return new ResponseEntity<>("{\"status\" : \"UP\"}", HttpStatus.OK);
    }

রেসপন্স এন্টিটি ব্যবহার করা আমার কাছে শিল্পের অবস্থা বলে মনে হয় । +1
আলেকজান্ডার

5

যোগ produces = "application/json"মধ্যে @RequestMappingমত টীকা:

@RequestMapping(value = "api/login", method = RequestMethod.GET, produces = "application/json")

ইঙ্গিত: একটি ফেরতের মান হিসাবে, আমি ResponseEntity<List<T>>প্রকারটি ব্যবহার করার পরামর্শ দিই। কারণ জেএসএন শরীরে উত্পাদিত ডেটাগুলির একক সাধারণ স্ট্রিংয়ের পরিবর্তে তার বৈশিষ্ট্য অনুসারে একটি অ্যারে বা কোনও উপাদান হওয়া দরকার । এটি কখনও কখনও সমস্যার কারণ হতে পারে (যেমন Angular2 এ পর্যবেক্ষণযোগ্য)।

পার্থক্য:

Stringজসন হিসাবে ফিরে :"example"

List<String>জসন হিসাবে ফিরে :["example"]


3

@ResponseBodyটীকা যোগ করুন , যা আউটপুট স্ট্রিমে রিটার্ন ডেটা লিখবে।


1
এটি আমার পক্ষে কাজ করে না। আমার আছে@PostMapping(value = "/some-url", produces = APPLICATION_JSON_UTF8_VALUE)
aliopi

0

এই সমস্যাটি আমাকে পাগল করেছে: স্প্রিং এমন একটি শক্তিশালী সরঞ্জাম এবং তবুও, জেএসওএন হিসাবে আউটপুট স্ট্রিংয়ের মতো সহজ জিনিসটি কুৎসিত হ্যাক ছাড়া অসম্ভব বলে মনে হয়।

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

supportsপদ্ধতি নিশ্চিন্ত হন যে সমস্ত অনুরোধ দ্বারা পরিচালিত হয় করে নির্মিত হয় StringHttpMessageConverter(যেমন রূপান্তরকারী যে হ্যান্ডলগুলি সব কন্ট্রোলার যে প্লেইন স্ট্রিং আসতে আউটপুট) প্রসেস করা হয় এবং beforeBodyWriteপদ্ধতি, আমরা যা ক্ষেত্রেই নিয়ন্ত্রণ আমরা সাময়িক বিরতি এবং JSON আউটপুট রূপান্তর করতে চান (এবং সেই অনুসারে শিরোনাম সংশোধন করুন)।

@ControllerAdvice
class StringToJsonAdvice(val ob: ObjectMapper) : ResponseBodyAdvice<Any?> {
    
    override fun supports(returnType: MethodParameter, converterType: Class<out HttpMessageConverter<*>>): Boolean =
        converterType === StringHttpMessageConverter::class.java

    override fun beforeBodyWrite(
        body: Any?,
        returnType: MethodParameter,
        selectedContentType: MediaType,
        selectedConverterType: Class<out HttpMessageConverter<*>>,
        request: ServerHttpRequest,
        response: ServerHttpResponse
    ): Any? {
        return if (request.uri.path.contains("api")) {
            response.getHeaders().contentType = MediaType.APPLICATION_JSON
            ob.writeValueAsString(body)
        } else body
    }
}

আমি ভবিষ্যতে আশা করি যে আমরা একটি সাধারণ টীকা পেয়ে যাব যাতে আমরা ওভাররাইড করতে পারি যা HttpMessageConverterআউটপুটটির জন্য ব্যবহার করা উচিত।


-5

আপনার পদ্ধতিতে এই টীকা যুক্ত করুন

@RequestMapping(value = "/getString", method = RequestMethod.GET, produces = "application/json")
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.