HALBuilder With Jersey to return JSON without escape

1,309 views
Skip to first unread message

Chen Conan

unread,
May 29, 2013, 1:48:58 AM5/29/13
to halbuil...@googlegroups.com
How can I get json string from my hello webservice as
{"_links":{"self":{"href":"Hello"},"friend":{"href":"World"}},"name":"Hello","year":"2013"}
not
"{\"_links\":{\"self\":{\"href\":\"Hello\"},\"friend\":{\"href\":\"World\"}},\"name\":\"Hello\",\"year\":\"2013\"}"

Thanks. 



1. I created a HelloResource.java 

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;

import org.springframework.stereotype.Component;

import com.theoryinpractise.halbuilder.DefaultRepresentationFactory;
import com.theoryinpractise.halbuilder.api.Representation;
import com.theoryinpractise.halbuilder.api.RepresentationFactory;

@Component
@Path("/hello")
public class HelloResource {

@GET
@Path("/world.json")
@Produces(MediaType.APPLICATION_JSON)
public Response sayHelloJson() {
RepresentationFactory representationFactory = new DefaultRepresentationFactory();

Representation hello = representationFactory.newRepresentation("Hello")
.withLink("friend", "World").withProperty("name", "Hello")
.withProperty("year", "2013");

String json = hello.toString(RepresentationFactory.HAL_JSON);
System.out.println(json);

return Response.ok().entity(json).build();

}
}

2. $ curl -X GET http://localhost:8080/ws/hello/world.json  and got result as 
"{\"_links\":{\"self\":{\"href\":\"Hello\"},\"friend\":{\"href\":\"World\"}},\"name\":\"Hello\",\"year\":\"2013\"}"

while on my eclipse console log was:
{"_links":{"self":{"href":"Hello"},"friend":{"href":"World"}},"name":"Hello","year":"2013"}

3. I want curl command will also return the same result as the console log, How?
{"_links":{"self":{"href":"Hello"},"friend":{"href":"World"}},"name":"Hello","year":"2013"}






Abiel Woldu

unread,
Jun 26, 2013, 1:54:41 AM6/26/13
to halbuil...@googlegroups.com
I used HalBuilder-Core-2.0.1.jar and HalBuilder-Api-2.0.1.jar and it works fine. Try those versions.

Mark Derricutt

unread,
Jun 26, 2013, 5:30:37 AM6/26/13
to halbuil...@googlegroups.com
Sorry I've not replied sooner ( been busy with work ), I'm not that familiar with JaxRS so not 100% sure, but from what I read in your sample code, it's doing exactly what you've asked.

Your method is declared as returning application/json, and you're setting a String as the body of your entity, so JaxRS is string serializing your String to a JSON object, which is correctly a "xxx" with escaped embedded quotes.

I suspect you need to change the "Response.ok().entity(json).build()" line and build a Response object that writes to the output stream directly or something.  I believe JaxRS uses the MediaType instance in the annotation to lookup an object serializer.

Mark Derricutt

unread,
Jun 26, 2013, 5:33:27 AM6/26/13
to halbuil...@googlegroups.com
Also - halbuilder-core 3.0.1 ( and halbuilder-json 3.0.1 ) released:

http://www.theoryinpractice.net/post/53084246214/halbuilder-3-0-1-released

I'm behind in a few things ( updating docs, posting to this list etc. )

Abiel Woldu wrote:
--
You received this message because you are subscribed to the Google
Groups "HALBuilder Development" group.
To unsubscribe from this group and stop receiving emails from it, send
an email to halbuilder-de...@googlegroups.com.
To post to this group, send email to halbuil...@googlegroups.com.
To view this discussion on the web visit
https://groups.google.com/d/msgid/halbuilder-dev/10149a39-6047-4425-a24e-5f6b859524a3%40googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.

Abiel Woldu

unread,
Jun 26, 2013, 2:04:18 PM6/26/13
to halbuil...@googlegroups.com
Hi Mark,
Thanks, I had a similar issue but with collection of objects. I basically wanted to have a JSONarray of resources in _embedded but I was not able to.

{
    "_embedded": {
        "http://.../rels/detail": [
            { },
{ }
]
Is this a legit issue in 2.0.1? if so is it addressed in 3.0.1??

Thanks

Cliff Redmond

unread,
Jun 26, 2013, 4:05:48 PM6/26/13
to halbuil...@googlegroups.com
.. sorry, premature send.

Basically; have one resource embed the HAL representation of another resource using withRepresentation().

Hope this helps,

Cliff.


On 26 June 2013 21:02, Cliff Redmond <cliff....@gmail.com> wrote:
Hi all,

to embed an object, enable its Jersey Provider to return a HAL representation and embed that representation using 

@Context private ResourceContext rc;

Representation halResource = representationFactory.newRepresentation();

  halResource.
withLink(...).withProperty(...).

 .withRepresentation("embedded_object", rc.getResource(EmbeddedResource.class).getHalRepresentation(this.getEmbeddedResource()))



Cliff Redmond

unread,
Jun 26, 2013, 4:02:51 PM6/26/13
to halbuil...@googlegroups.com
Hi all,

to embed an object, enable its Jersey Provider to return a HAL representation and embed that representation using 

@Context private ResourceContext rc;

Representation halResource = representationFactory.newRepresentation();

  halResource.
withLink(...).withProperty(...).

 .withRepresentation("embedded_object", rc.getResource(EmbeddedResource.class).getHalRepresentation(this.getEmbeddedResource()))

On 26 June 2013 19:04, Abiel Woldu <abiel....@gmail.com> wrote:

Mark Derricutt

unread,
Jun 26, 2013, 4:32:15 PM6/26/13
to halbuil...@googlegroups.com
Where is this resource context coming from that supports Hal?

Cliff Redmond wrote:
> .withRepresentation("embedded_object",
> rc.getResource(EmbeddedResource.class).getHalRepresentation(this.getEmbeddedResource()))

Mark Derricutt

unread,
Jun 26, 2013, 4:41:00 PM6/26/13
to halbuil...@googlegroups.com
If you simply make multiple calls to withRepresentation with each embedded resource they'll be generated as a JSONarray under that rel.

There's no specific support for this in the API as its quite simple to just loop your array and do those calls, even more so if/when you're using a language with lambda support that I didn't really think it made sense to add a withRepresentations plural method.

There is the withRepresentable(Representable r) method tho, which you can pass anything that implements that interface as a point of reverse delegation, i.e. you could have say a RepresentableCollection class which wrapped a Collection and added each element. In Scala for instance you could make that an implicit conversion etc.

Mark

Cliff Redmond

unread,
Jun 26, 2013, 5:21:05 PM6/26/13
to halbuil...@googlegroups.com
Sorry, it should have been a Jersey @Provider class pulled from the ResourceContext:

.withRepresentation("embedded_object", rc.getResource(EmbeddedResourceMessageBodyWriter.class).getHalRepresentation(this.getEmbeddedResource()))

Forgive me, I was trying to generalise a concrete example...

The providers generate Hal Representations via getHalRepresentation() 

their writeTo() methods call 

toString(RepresentationFactory.HAL_JSON, Sets.newHashSet(RepresentationFactory.PRETTY_PRINT));

on the Representation.

Regards,

Cliff.

--
You received this message because you are subscribed to the Google Groups "HALBuilder Development" group.
To unsubscribe from this group and stop receiving emails from it, send an email to halbuilder-dev+unsubscribe@googlegroups.com.
To post to this group, send email to halbuilder-dev@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/halbuilder-dev/51CB4FCF.90204%40talios.com.

Mark Derricutt

unread,
Jun 26, 2013, 6:19:36 PM6/26/13
to halbuil...@googlegroups.com
Cliff Redmond wrote:
Sorry, it should have been a Jersey @Provider class pulled from the ResourceContext:

.withRepresentation("embedded_object", rc.getResource(EmbeddedResourceMessageBodyWriter.class).getHalRepresentation(this.getEmbeddedResource()))

Ah nice - that would make a good additional library for a halbuider-jaxrs library actually for others to reuse. Now that EE7 is out I was hoping to try find some time to checkout the new Jersey 2.0 and RestEasy 3 and make up a small repo that provides this extension, but if you've already got some code we could base it off that would be awesome.

Abiel Woldu

unread,
Jun 26, 2013, 7:10:14 PM6/26/13
to halbuil...@googlegroups.com
Thanks Mark and Cliff.

The repeated call on withRepresentation( "myKey", rep ) did the trick. But that was a bit hidden in terms of design. If I call it once it makes a JSONObject that is retrieved using "myKey" but if i make multiple calls it gives me a JSONArray that is retrieved by "myKey". So "myKey" is used to retrieve Objects and Arrays. This is a bit inconsistent. Why not create an array of one element for a single call of withRepresentation( "key", val )?
The check for "am i getting an object or an array" will unnecessarily be done in the client; before starting reading the object. I found that a bit unintuitive. But it's minor issue.

Cliff, we are using ApacheCXF but I think ur idea would be a cool Hal4Jersey add on library.

Thanks,
Abiel

Mark Derricutt

unread,
Jun 26, 2013, 8:07:49 PM6/26/13
to halbuil...@googlegroups.com
I'm with you on this. This is as-per HAL spec (
http://tools.ietf.org/html/draft-kelly-json-hal-05#section-4.1.2 ) as is
something I've often found irksome, which is also why there are
Javascript HAL libraries - just because one CAN use the HAL JSON object
inline, doesn't always mean one should ( it is after all a
serialization/deserialization format ).

Under the XML variant you ALWAYS get a list of elements such as:

<resource>
<resource rel="myKey"/>
<resource rel="myKey"/>
<resource rel="myKey"/>
</resource>

as XML allows for repeating elements, but under JSON you can only have
one key - apparently it's common in JS land to do the object/array pattern.

You could add your own "getLink" or "getEmbedded" function that lifts
the single into an array, and process it consistently, or even have that
function be higher-ordered and take in a function to apply to each
link/embed etc.
Reply all
Reply to author
Forward
0 new messages