Spring MVC, force JSON response in plain request - json

I am using Spring 3.0.6 and i have a single controller for uploading files to the server. I am using a script to upload using XmlHttpRequest for browsers that support it while the rest of the browsers submit a (hidden) multipart form. The problem however is that when a form is submitted it sends the following header:
Accept text/html, application/xhtml+xml, */*
I figure that due to this header the Controller which is marked with #ResponseBody replies with the response been converted to XML instead of JSON. Is there a way to get around this without hacking the form submit request?

You can force JSON using #RequestMapping(produces = "application/json"). I don't remember if this is available in 3.0 but it is available in 3.1 and 3.2 for sure.
As others noted, Jackson needs to be on your classpath.

Thank you! I was having exactly the same issue and your post resolved my problem.
On the UI I'm using JQuery with this file upload plugin:
https://github.com/blueimp/jQuery-File-Upload/wiki
Here's my completed method (minus the biz logic):
#RequestMapping(value = "/upload", method = RequestMethod.POST)
public void handleUpload( #RequestParam("fileToUpload") CommonsMultipartFile uploadFile, ServletResponse response){
List<UploadStatus> status = new ArrayList<UploadStatus>();
UploadStatus uploadStatus = new UploadStatus();
status.add(uploadStatus);
if(uploadFile == null || StringUtils.isBlank(uploadFile.getOriginalFilename())){
uploadStatus.setMessage(new Message(MessageType.important, "File name must be specified."));
}else{
uploadStatus.setName(uploadFile.getOriginalFilename());
uploadStatus.setSize(uploadFile.getSize());
}
ObjectMapper mapper = new ObjectMapper();
try {
JsonGenerator generator = mapper.getJsonFactory().createJsonGenerator(response.getOutputStream(), JsonEncoding.UTF8);
mapper.writeValue(generator, status);
generator.flush();
} catch (Exception e) {
e.printStackTrace();
}
}

If you want a JSON response, you can easily accomplish that by having the Jackson JARs on your classpath. Spring will auto-magically pick up on them being there and will convert your #ResponseBody to JSON.

I made it work by getting rid off #ResponseBody and instead doing manually the conversion (always using Jackson), i.e.
Response r = new Response();
ObjectMapper mapper = new ObjectMapper();
JsonGenerator generator = mapper.getJsonFactory().createJsonGenerator(response.getOutputStream(), JsonEncoding.UTF8);
try {
File f = uploadService.getAjaxUploadedFile(request);
r.setData(f.getName());
} catch (Exception e) {
logger.info(e.getMessage());
r = new Response(new ResponseError(e.getMessage(), ""));
}
mapper.writeValue(generator, r);
generator.flush();
Does anyone know another way? I tried setting up a ContentNegotiatingViewResolver but i don't want to break any other controllers by assigning all hmtl to json. Also, i tried to do it for this method only via a custom viewresolver but when i setup a jsonview and use BeanNameViewResolver although the response is correctly converted to JSON the server throws an
HttpRequestMethodNotSupportedException: exception, with Request method 'POST' not supported and set status to 404.

Related

Sending a JSON in batches

I have some doubts on how to perform some tasks I use jackson to create a JSON, after I encrypt I need to do it sent to a service that will consume this JSON, the problem is that the file size (physical) is 3,571 KB and I need to send in batches of at most 1,000KB
each one, as I am newcomer with springBoot and web in general I saw that I have to do something called pagination, is that it?
I have a Dto (students) a class manager where I make access to the database that returns me a list of students
Then I create json, step to base 64 to finally configure the header and make the request
studentList= StudantManager.getAllStudants(con);
int sizeRecords = studentList.size();
try {
students= useful.convertToJson(studentList);
studentsWithSecurity = useful.securityJson(students);
} catch (JsonProcessingException e) {
log.error(e.toString());
}
RestTemplate restTemplate = new RestTemplate();
String url = "myRestService";
HttpHeaders headers;
headers=getHeaders(sizeRecords,students);
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<String> entity = new HttpEntity<>(studentsWithSecurity, headers);
String answer = restTemplate.postForObject(url, entity, String.class);
Taking advantage of my current code, how can I create a solution that solves the upload problem that I mentioned above?

Cannot access Restlet service using POST from SOAP UI

I created a series of REST services in Java using Restlets. The majority of these services use JSON, and I have no problem accessing them using SOAP UI via a GET request. However, when I try to access POST based services using SOAP UI, the Representation entity parameter is always null. I have searched Stack Overflow as well as the web, but could find nothing which I either haven't already done, or which addresses my problem.
Here is the code for a POST resource which always seems to receive a null entity:
public class CreateAccountResource extends ServerResource {
#Post("json")
public Representation createAccount(Representation entity) throws IOException {
String message = null;
boolean result = true;
try {
String post = entity.getText();
Object obj = new JSONParser().parse(post);
JSONObject jsonObject = (JSONObject) obj;
String username = (String) jsonObject.get("username");
String password = (String) jsonObject.get("password");
String email = (String) jsonObject.get("email");
// more code
}
catch (Exception e) {
// handle exception here
}
}
}
And here is a screen shot from my SOAP UI showing the configuration I used when sending the request:
In case you are wondering, I am using IntelliJ in debug mode to inspect the value of the entity, and the project uses Maven.
I never use Restlet however I think that since you specify #Post("json") annotation for your createAccount method; the method is waiting for a json in the POST body instead of passing the values as a query parameters.
So probably you must change your actual POST with the query parameters to a POST call to your URL http://localhost:8080/MyApp/service/createAccount passing the parameters in the body as json:
{
"username" : "tim",
"password" : "password",
"email" : "tim#me.com"
}
In SOAPUI could be something like:
Hope it helps,

How to Get a Json from api/metrics of sonarqube?

I tried to use the GET method of api/metrics to retrieve a JSON to use for my program, but the documentation lack to describe all the parameter to use in the requestUrl.
for example in for my program I find, using the Google Chrome console, that the requestUrl is this one:
http://localhost:9000/api/resources?resource=my%3AjavaSample%3AMandria%2Fsrc%2Fmandria%2FIllnessException.java&metrics=new_technical_debt%2Cblocker_violations%2Cburned_budget%2Cbusiness_value%2Cclasses%2Ccomment_lines%2Ccomment_lines_density%2Ccomplexity%2Cclass_complexity%2Cfile_complexity%2Cfunction_complexity%2Cbranch_coverage%2Cnew_it_branch_coverage%2Cnew_branch_coverage%2Cconfirmed_issues%2Ccoverage%2Cnew_it_coverage%2Cnew_coverage%2Ccritical_violations%2Cdirectories%2Cduplicated_blocks%2Cduplicated_files%2Cduplicated_lines%2Cduplicated_lines_density%2Cfalse_positive_issues%2Cpackage_tangles%2Cfiles%2Cfile_complexity_distribution%2Cfunctions%2Cfunction_complexity_distribution%2Cgenerated_lines%2Cgenerated_ncloc%2Cit_branch_coverage%2Cit_coverage%2Cit_line_coverage%2Cit_uncovered_conditions%2Cit_uncovered_lines%2Cinfo_violations%2Cviolations%2Cline_coverage%2Cnew_it_line_coverage%2Cnew_line_coverage%2Clines%2Cncloc%2Clines_to_cover%2Cnew_it_lines_to_cover%2Cnew_lines_to_cover%2Cmajor_violations%2Cminor_violations%2Cnew_blocker_violations%2Cnew_critical_violations%2Cnew_info_violations%2Cnew_major_violations%2Cnew_minor_violations%2Cnew_violations%2Copen_issues%2Coverall_branch_coverage%2Cnew_overall_branch_coverage%2Coverall_coverage%2Cnew_overall_coverage%2Coverall_line_coverage%2Cnew_overall_line_coverage%2Cnew_overall_lines_to_cover%2Coverall_uncovered_conditions%2Cnew_overall_uncovered_conditions%2Coverall_uncovered_lines%2Cnew_overall_uncovered_lines%2Cpackage_cycles%2Cpackage_feedback_edges%2Cpackage_tangle_index%2Cprojects%2Cpublic_api%2Cpublic_documented_api_density%2Cpublic_undocumented_api%2Calert_status%2Creopened_issues%2Csqale_rating%2Cskipped_tests%2Cstatements%2Cteam_size%2Csqale_index%2Csqale_debt_ratio%2Cuncovered_conditions%2Cnew_it_uncovered_conditions%2Cnew_uncovered_conditions%2Cuncovered_lines%2Cnew_it_uncovered_lines%2Cnew_uncovered_lines%2Ctests%2Ctest_execution_time%2Ctest_errors%2Ctest_failures%2Ctest_success_density
is it possible to find a more detailed documentation or the way I try to solve my problem is not the correct one?
Just add &format=json to the parameters.
See http://docs.sonarqube.org/display/SONARQUBE43/Web+Service+API#WebServiceAPI-ResponseFormats
In response to your question how to call from a outside comment:
If you want to call the SonarQube Web Service API from a Java program you can use the Apache HTTP Client:
public static void main(String[] args) throws ClientProtocolException, IOException {
HttpGet httpGet = new HttpGet("http://localhost:9000/api/resources?metrics=lines");
try(CloseableHttpClient httpClient = HttpClients.createDefault();
CloseableHttpResponse response = httpClient.execute(httpGet);) {
System.out.println(response.getStatusLine());
HttpEntity entity = response.getEntity();
System.out.println(EntityUtils.toString(entity));
}
}
In this case it prints all projects on SonarQube and additionaly the metric "lines". You can add multiple metrics to the list, separated by a comma:
"http://localhost:9000/api/resources?metrics=lines,blocker_violations"

How do I get ASP.NET Web API to return JSON instead of XML using Chrome?

This question's answers are a community effort. Edit existing answers to improve this post. It is not currently accepting new answers or interactions.
Using the newer ASP.NET Web API, in Chrome I am seeing XML - how can I change it to request JSON so I can view it in the browser? I do believe it is just part of the request headers, am I correct in that?
Note: Read the comments of this answer, it can produce a XSS Vulnerability if you are using the default error handing of WebAPI
I just add the following in App_Start / WebApiConfig.cs class in my MVC Web API project.
config.Formatters.JsonFormatter.SupportedMediaTypes
.Add(new MediaTypeHeaderValue("text/html") );
That makes sure you get JSON on most queries, but you can get XML when you send text/xml.
If you need to have the response Content-Type as application/json please check Todd's answer below.
NameSpace is using System.Net.Http.Headers.
If you do this in the WebApiConfig you will get JSON by default, but it will still allow you to return XML if you pass text/xml as the request Accept header.
Note: This removes the support for application/xml
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
var appXmlType = config.Formatters.XmlFormatter.SupportedMediaTypes.FirstOrDefault(t => t.MediaType == "application/xml");
config.Formatters.XmlFormatter.SupportedMediaTypes.Remove(appXmlType);
}
}
If you are not using the MVC project type and therefore did not have this class to begin with, see this answer for details on how to incorporate it.
Using RequestHeaderMapping works even better, because it also sets the Content-Type = application/json in the response header, which allows Firefox (with JSONView add-on) to format the response as JSON.
GlobalConfiguration.Configuration.Formatters.JsonFormatter.MediaTypeMappings
.Add(new System.Net.Http.Formatting.RequestHeaderMapping("Accept",
"text/html",
StringComparison.InvariantCultureIgnoreCase,
true,
"application/json"));
I like Felipe Leusin's approach best - make sure browsers get JSON without compromising content negotiation from clients that actually want XML. The only missing piece for me was that the response headers still contained content-type: text/html. Why was that a problem? Because I use the JSON Formatter Chrome extension, which inspects content-type, and I don't get the pretty formatting I'm used to. I fixed that with a simple custom formatter that accepts text/html requests and returns application/json responses:
public class BrowserJsonFormatter : JsonMediaTypeFormatter
{
public BrowserJsonFormatter() {
this.SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/html"));
this.SerializerSettings.Formatting = Formatting.Indented;
}
public override void SetDefaultContentHeaders(Type type, HttpContentHeaders headers, MediaTypeHeaderValue mediaType) {
base.SetDefaultContentHeaders(type, headers, mediaType);
headers.ContentType = new MediaTypeHeaderValue("application/json");
}
}
Register like so:
config.Formatters.Add(new BrowserJsonFormatter());
MVC4 Quick Tip #3–Removing the XML Formatter from ASP.Net Web API
In Global.asax add the line:
GlobalConfiguration.Configuration.Formatters.XmlFormatter.SupportedMediaTypes.Clear();
like so:
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
BundleTable.Bundles.RegisterTemplateBundles();
GlobalConfiguration.Configuration.Formatters.XmlFormatter.SupportedMediaTypes.Clear();
}
In the WebApiConfig.cs, add to the end of the Register function:
// Remove the XML formatter
config.Formatters.Remove(config.Formatters.XmlFormatter);
Source.
In the Global.asax I am using the code below. My URI to get JSON is http://www.digantakumar.com/api/values?json=true
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
GlobalConfiguration.Configuration.Formatters.JsonFormatter.MediaTypeMappings.Add(new QueryStringMapping("json", "true", "application/json"));
}
Have a look at content negotiation in the WebAPI. These (Part 1 & Part 2) wonderfully detailed and thorough blog posts explain how it works.
In short, you are right, and just need to set the Accept or Content-Type request headers. Given your Action isn't coded to return a specific format, you can set Accept: application/json.
As the question is Chrome-specific, you can get the Postman extension which allows you to set the request content type.
This code makes json my default and allows me to use the XML format as well. I'll just append the xml=true.
GlobalConfiguration.Configuration.Formatters.XmlFormatter.MediaTypeMappings.Add(new QueryStringMapping("xml", "true", "application/xml"));
GlobalConfiguration.Configuration.Formatters.JsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/html"));
Thanks everyone!
One quick option is to use the MediaTypeMapping specialization. Here is an example of using QueryStringMapping in the Application_Start event:
GlobalConfiguration.Configuration.Formatters.JsonFormatter.MediaTypeMappings.Add(new QueryStringMapping("a", "b", "application/json"));
Now whenever the url contains the querystring ?a=b in this case, Json response will be shown in the browser.
Don't use your browser to test your API.
Instead, try to use an HTTP client that allows you to specify your request, such as CURL, or even Fiddler.
The problem with this issue is in the client, not in the API. The web API behaves correctly, according to the browser's request.
Most of the above answers makes perfect sense.
Since you are seeing data being formatted in XML format ,that means XML formatter is applied,SO you can see JSON format just by removing the XMLFormatter from the HttpConfiguration parameter like
public static void Register(HttpConfiguration config)
{
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
config.Formatters.Remove(config.Formatters.XmlFormatter);
config.EnableSystemDiagnosticsTracing();
}
since JSON is the default format
Returning the correct format is done by the media-type formatter.
As others mentioned, you can do this in the WebApiConfig class:
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
...
// Configure Web API to return JSON
config.Formatters.JsonFormatter
.SupportedMediaTypes.Add(new System.Net.Http.Headers.MediaTypeHeaderValue("text/html"));
...
}
}
For more, check:
Media Formatters in ASP.NET Web API 2.
Content Negotiation in ASP.NET Web API.
In case your actions are returning XML (which is the case by default) and you need just a specific method to return JSON, you can then use an ActionFilterAttribute and apply it to that specific action.
Filter attribute:
public class JsonOutputAttribute : ActionFilterAttribute
{
public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
{
ObjectContent content = actionExecutedContext.Response.Content as ObjectContent;
var value = content.Value;
Type targetType = actionExecutedContext.Response.Content.GetType().GetGenericArguments()[0];
var httpResponseMsg = new HttpResponseMessage
{
StatusCode = HttpStatusCode.OK,
RequestMessage = actionExecutedContext.Request,
Content = new ObjectContent(targetType, value, new JsonMediaTypeFormatter(), (string)null)
};
actionExecutedContext.Response = httpResponseMsg;
base.OnActionExecuted(actionExecutedContext);
}
}
Applying to action:
[JsonOutput]
public IEnumerable<Person> GetPersons()
{
return _repository.AllPersons(); // the returned output will be in JSON
}
Note that you can omit the word Attribute on the action decoration and use just [JsonOutput] instead of [JsonOutputAttribute].
I used a global action filter to remove Accept: application/xml when the User-Agent header contains "Chrome":
internal class RemoveXmlForGoogleChromeFilter : IActionFilter
{
public bool AllowMultiple
{
get { return false; }
}
public async Task<HttpResponseMessage> ExecuteActionFilterAsync(
HttpActionContext actionContext,
CancellationToken cancellationToken,
Func<Task<HttpResponseMessage>> continuation)
{
var userAgent = actionContext.Request.Headers.UserAgent.ToString();
if (userAgent.Contains("Chrome"))
{
var acceptHeaders = actionContext.Request.Headers.Accept;
var header =
acceptHeaders.SingleOrDefault(
x => x.MediaType.Contains("application/xml"));
acceptHeaders.Remove(header);
}
return await continuation();
}
}
Seems to work.
In the latest version of ASP.net WebApi 2, under WebApiConfig.cs, this will work:
config.Formatters.Remove(GlobalConfiguration.Configuration.Formatters.XmlFormatter);
config.Formatters.Add(GlobalConfiguration.Configuration.Formatters.JsonFormatter);
I found the Chrome app "Advanced REST Client" excellent to work with REST services. You can set the Content-Type to application/json among other things:
Advanced REST client
config.Formatters.Remove(config.Formatters.XmlFormatter);
It's unclear to me why there is all of this complexity in the answer. Sure there are lots of ways you can do this, with QueryStrings, headers and options... but what I believe to be the best practice is simple. You request a plain URL (ex: http://yourstartup.com/api/cars) and in return you get JSON. You get JSON with the proper response header:
Content-Type: application/json
In looking for an answer to this very same question, I found this thread, and had to keep going because this accepted answer doesn't work exactly. I did find an answer which I feel is just too simple not to be the best one:
Set the default WebAPI formatter
I'll add my tip here as well.
WebApiConfig.cs
namespace com.yourstartup
{
using ...;
using System.Net.Http.Formatting;
...
config.Formatters.Clear(); //because there are defaults of XML..
config.Formatters.Add(new JsonMediaTypeFormatter());
}
I do have a question of where the defaults (at least the ones I am seeing) come from. Are they .NET defaults, or perhaps created somewhere else (by someone else on my project). Anways, hope this helps.
You can use as below:
GlobalConfiguration.Configuration.Formatters.Clear();
GlobalConfiguration.Configuration.Formatters.Add(new JsonMediaTypeFormatter());
Here is a solution similar to jayson.centeno's and other answers, but using the built-in extension from System.Net.Http.Formatting.
public static void Register(HttpConfiguration config)
{
// add support for the 'format' query param
// cref: http://blogs.msdn.com/b/hongyes/archive/2012/09/02/support-format-in-asp-net-web-api.aspx
config.Formatters.JsonFormatter.AddQueryStringMapping("$format", "json", "application/json");
config.Formatters.XmlFormatter.AddQueryStringMapping("$format", "xml", "application/xml");
// ... additional configuration
}
The solution was primarily geared toward supporting $format for OData in the early releases of WebApi, but it also applies to the non-OData implementation, and returns the
Content-Type: application/json; charset=utf-8 header in the response.
It allows you to tack &$format=json or &$format=xml to the end of your uri when testing with a browser. It does not interfere with other expected behavior when using a non-browser client where you can set your own headers.
Just add those two line of code on your WebApiConfig class
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
//add this two line
config.Formatters.Clear();
config.Formatters.Add(new JsonMediaTypeFormatter());
............................
}
}
You just change the App_Start/WebApiConfig.cs like this:
public static void Register(HttpConfiguration config)
{
// Web API configuration and services
// Web API routes
config.MapHttpAttributeRoutes();
//Below formatter is used for returning the Json result.
var appXmlType = config.Formatters.XmlFormatter.SupportedMediaTypes.FirstOrDefault(t => t.MediaType == "application/xml");
config.Formatters.XmlFormatter.SupportedMediaTypes.Remove(appXmlType);
//Default route
config.Routes.MapHttpRoute(
name: "ApiControllerOnly",
routeTemplate: "api/{controller}"
);
}
Some time has passed since this question was asked (and answered) but another option is to override the Accept header on the server during request processing using a MessageHandler as below:
public class ForceableContentTypeDelegationHandler : DelegatingHandler
{
protected async override Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request,
CancellationToken cancellationToken)
{
var someOtherCondition = false;
var accHeader = request.Headers.GetValues("Accept").FirstOrDefault();
if (someOtherCondition && accHeader.Contains("application/xml"))
{
request.Headers.Remove("Accept");
request.Headers.Add("Accept", "application/json");
}
return await base.SendAsync(request, cancellationToken);
}
}
Where someOtherCondition can be anything including browser type, etc. This would be for conditional cases where only sometimes do we want to override the default content negotiation. Otherwise as per other answers, you would simply remove an unnecessary formatter from the configuration.
You'll need to register it of course. You can either do this globally:
public static void Register(HttpConfiguration config) {
config.MessageHandlers.Add(new ForceableContentTypeDelegationHandler());
}
or on a route by route basis:
config.Routes.MapHttpRoute(
name: "SpecialContentRoute",
routeTemplate: "api/someUrlThatNeedsSpecialTreatment/{id}",
defaults: new { controller = "SpecialTreatment" id = RouteParameter.Optional },
constraints: null,
handler: new ForceableContentTypeDelegationHandler()
);
And since this is a message handler it will run on both the request and response ends of the pipeline much like an HttpModule. So you could easily acknowledge the override with a custom header:
public class ForceableContentTypeDelegationHandler : DelegatingHandler
{
protected async override Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request,
CancellationToken cancellationToken)
{
var wasForced = false;
var someOtherCondition = false;
var accHeader = request.Headers.GetValues("Accept").FirstOrDefault();
if (someOtherCondition && accHeader.Contains("application/xml"))
{
request.Headers.Remove("Accept");
request.Headers.Add("Accept", "application/json");
wasForced = true;
}
var response = await base.SendAsync(request, cancellationToken);
if (wasForced){
response.Headers.Add("X-ForcedContent", "We overrode your content prefs, sorry");
}
return response;
}
}
Here is the easiest way that I have used in my applications. Add given below 3 lines of code in App_Start\WebApiConfig.cs in the Register function:
var formatters = GlobalConfiguration.Configuration.Formatters;
formatters.Remove(formatters.XmlFormatter);
config.Formatters.JsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("application/json"));
Asp.net web API will automatically serialize your returning object to JSON and as the application/json is added in the header so the browser or the receiver will understand that you are returning JSON result.
From MSDN Building a Single Page Application with ASP.NET and AngularJS (about 41 mins in).
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// ... possible routing etc.
// Setup to return json and camelcase it!
var formatter = GlobalConfiguration.Configuration.Formatters.JsonFormatter;
formatter.SerializerSettings.ContractResolver =
new Newtonsoft.Json.Serialization.CamelCasePropertyNamesContractResolver();
}
It should be current, I tried it and it worked.
Using Felipe Leusin's answer for years, after a recent update of core libraries and of Json.Net, I ran into a System.MissingMethodException:SupportedMediaTypes.
The solution in my case, hopefully helpful to others experiencing the same unexpected exception, is to install System.Net.Http. NuGet apparently removes it in some circumstances. After a manual installation, the issue was resolved.
WebApiConfig is the place where you can configure whether you want to output in json or xml. By default, it is xml. In the register function, we can use HttpConfiguration Formatters to format the output.
System.Net.Http.Headers => MediaTypeHeaderValue("text/html") is required to get the output in the json format.
I'm astonished to see so many replies requiring coding to change a single use case (GET) in one API instead of using a proper tool what has to be installed once and can be used for any API (own or 3rd party) and all use cases.
So the good answer is:
If you only want to request json or other content type install Requestly or a similar tool and modify the Accept header.
If you want to use POST too and have nicely formatted json, xml, etc. use a proper API testing extension like Postman or ARC.

How to override response header in jersey client

I have a jersey client that I am trying to unmarshall a response entity with. The problem is the remote web service sends back application/octet-stream as the content type so Jersey does not know how to unmarshall it (I have similar errors with text/html coming back for XML and such). I cannot change the web service.
What I want to do is override the content-type and change it to application/json so jersey will know which marshaller to use.
I cannot register application/octet-stream with the json marshaller as for a given content type I actually might be getting back all kinds of oddities.
As laz pointed out, ClientFilter is the way to go:
client.addFilter(new ClientFilter() {
#Override
public ClientResponse handle(ClientRequest request) throws ClientHandlerException {
request.getHeaders().putSingle(HttpHeaders.CONTENT_TYPE, "application/json");
return getNext().handle(request);
}
});
I'm not well-versed in the Jersey client API, but can you use a ClientFilter to do this? Perhaps you could add a property to the request via ClientRequest.getProperties().put(String, Object) that tells the ClientFilter what Content-Type to override the response with. If the ClientFilter finds the override property, it uses it, otherwise it does not alter the response. I'm not sure if the ClientFilter is invoked prior to any unmarshalling though. Hopefully it is!
Edit (Have you tried something like this):
public class ContentTypeClientFilter implements ClientFilter {
#Override
public ClientResponse handle(ClientRequest request) throws ClientHandlerException {
final ClientResponse response = getNext().handle(request);
// check for overridden ContentType set by other code
final String overriddenContentType = request.getProperties().get("overridden.content.type");
if (overriddenContentType != null) {
response.getHeaders().putSingle(HttpHeaders.CONTENT_TYPE, overriddenContentType);
}
return response;
}
}
Under Java 8 and Jersey 2 you can do it with a lambda:
client.register((ClientResponseFilter) (requestContext, responseContext) ->
responseContext.getHeaders().putSingle("Content-Type", "application/json"));