What ObjectMapper config / annotations required for successful JSON / JSON array exhange using Jackson 2.2 - arrays

Using Jackson 2.2.2 and Apache CXF web services client and server API.
I'm finding it impossible to serialize / deserialize JSON without failure.
Java class:
MyPojo
{
..... various properties
}
JSON produced from Jackson:
{
"MyPojo":
{
..... various properties
}
}
When I send the exact same JSON back to Jackson for it to consume, it fails with:
com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException:
Unrecognized field "MyPojo" (class app.model.MyPojo), not marked as ignorable (17 known properties: ,.....
Ideally, Jackson would not wrap the MyPojo object with {"MyPojo":} because I only ever exchange MyPojo objects, so it is implied.
To that end, how can I get Jackson to produce:
{
..... various properties
}
Then, how do I get jackson to consume the same JSON without failing? i.e. what ObjectMapper configuration or annotations or combination of both do I have to use?
If this is impossible, then how do I configure / annotate to get Jackson to consume the "wrapped" JSON without failing?
ALSO,
I have the same issues when producing / consuming an array of MyPojo objects:
JSON produced from Jackson:
{
"MyPojo":
[
{
..... various properties
},
{
..... various properties
}
]
}
..when consumed fails with:
com.fasterxml.jackson.databind.JsonMappingException:
Can not deserialize instance of app.model.MyPojo[] out of START_OBJECT token
Again, ideally (but not essential) Jackson would produce / consume:
[
{
..... various properties
},
{
..... various properties
}
]
Note, the Apache CXF WS appears to perform some magic via its #GET, #POST, etc, annotations as when used in conjuntion with a RESTful WS resource method which returns a MyPojo object, i.e. it appears that after my method returns the object, it is transformed into JSON.
To that end, I am unsure if a local or even global ObjectMapper will influence the output, so this should also be considered when answering.
Another note, I also need the same POJO to be produced and consumed in XML via JAXB.
EDIT:
I am now quite certain that TomEE/CXF is not using Jackson and that this is the cause of my issues. I'll update when I get it to work.
RESOLVED:
Further investigation revealed that whilst the JSON was being deserailized by Jackson, the default Jettison provider was not being overriden with Jackson when serializing due to misconfiguration of default JSON provider in CXF/TomEE. This resulted in a Jackson - Jettison formatting mismatch.

On stackOverflow are more than many answered questions like yours.
This is a solution:
objectMapper.configure(SerializationConfig.Feature.WRAP_ROOT_VALUE, true);
You can see similar questions:
Use class name as root key for JSON Jackson serialization
Enable Jackson to not output the class name when serializing (using Spring MVC)

Related

Flask Restplus mutlipart/form-data model

Is it possible with Flask Restplus to create a model for a multipart/form-data request so that I can use it to validate the input with #api.expect?
I have this complex data structure for which I've created a api.namespace().model that has to be received together with a file. However when I tried to document the endpoint I noticed that this doesn't seem to be supported by Flask Restplus.
I've tried to find something along the lines of
parser = ns.parser()
parser.add_argument("jsonModel", type=Model, location="form")
parser.add_argument("file", type=FileStorage, location="files")
and
formModel = ns.model("myForm", {"jsonModel": fields.Nested(myModel), "file": fields.File})
But neither methods seem to support this kind of behavior.

Post an ndb StructuredProperty _Message__decoded_fields

My Problem:
I am attempting to fill a datastore model in GAE that contains an ndb.Structured Property() using a 'POST' request.
This question has been asked recently but not answered (How to “POST” ndb.StructuredProperty?)
I have the following two models:
class Check(EndpointsModel):
this = ndb.StringProperty()
that = ndb.StringProperty()
class CheckMessage(EndpointsModel):
check = ndb.StructuredProperty(Check)
I'm trying to post this data:
{
check:
{
"this":"test",
"that":"test"
}
}
with the following API request:
#CheckMessage.method(name='check_insert',path='check/insert',http_method='POST')
def check_insert(self,request):
print(request)
Upon posting from the client I receive the following error:
AttributeError: 'Check' object has no attribute '_Message__decoded_fields'
The Issue:
From my very high-level understanding of the endpoints-proto-datastore module it seems that when the json is being decoded and saved onto the incoming message (utils.py line 431) it's not checking for structured/localstructured properties and saving their keys as well which is all fine and dandy until FromValue (ndb/model.py line 115) checks for instances of structured properties and attempts to recursively convert the structured property from the protorpc message into a model entity (which needs the _Message__decoded_fields).
Sasxa (see the link above) had found a nifty little workaround to this issue by using an EndpointsAliasProperty converted to a ProtoRPC message class to bypass endpoints-proto-datastore's automatic conversion of the structuredproperty into its associated model entity, however this workaround had some side effects that made what I was trying to do difficult.
The Question:
Does anyone know how to correctly fill a datastore model containing a StructuredProperty using a 'POST' request, and are there any working examples of this available?

Parsing Swagger JSON data and storing it in .net class

I want to parse Swagger data from the JSON I get from {service}/swagger/docs/v1 into dynamically generated .NET class.
The problem I am facing is that different APIs can have different number of parameters and operations. How do I dynamically parse Swagger JSON data for different services?
My end result should be list of all APIs and it's operations in a variable on which I can perform search easily.
Did you ever find an answer for this? Today I wanted to do the same thing, so I used the AutoRest open source project from MSFT, https://github.com/Azure/autorest. While it looks like it's designed for generating client code (code to consume the API documented by your swagger document), at some point on the way producing this code it had to of done exactly what you asked in your question - parse the Swagger file and understand the operations, inputs and outputs the API supports.
In fact we can get at this information - AutoRest publically exposes this information.
So use nuget to install AutoRest. Then add a reference to AutoRest.core and AutoRest.Model.Swagger. So far I've just simply gone for:
using Microsoft.Rest.Generator;
using Microsoft.Rest.Generator.Utilities;
using System.IO;
...
var settings = new Settings();
settings.Modeler = "Swagger";
var mfs = new MemoryFileSystem();
mfs.WriteFile("AutoRest.json", File.ReadAllText("AutoRest.json"));
mfs.WriteFile("Swagger.json", File.ReadAllText("Swagger.json"));
settings.FileSystem = mfs;
var b = System.IO.File.Exists("AutoRest.json");
settings.Input = "Swagger.json";
Modeler modeler = Microsoft.Rest.Generator.Extensibility.ExtensionsLoader.GetModeler(settings);
Microsoft.Rest.Generator.ClientModel.ServiceClient serviceClient;
try
{
serviceClient = modeler.Build();
}
catch (Exception exception)
{
throw new Exception(String.Format("Something nasty hit the fan: {0}", exception.Message));
}
The swagger document you want to parse is called Swagger.json and is in your bin directory. The AutoRest.json file you can grab from their GitHub (https://github.com/Azure/autorest/tree/master/AutoRest/AutoRest.Core.Tests/Resource). I'm not 100% sure how it's used, but it seems it's needed to inform the tool about what is supports. Both JSON files need to be in your bin.
The serviceClient object is what you want. It will contain information about the methods, model types, method groups
Let me know if this works. You can try it with their resource files. I used their ExtensionLoaderTests for reference when I was playing around(https://github.com/Azure/autorest/blob/master/AutoRest/AutoRest.Core.Tests/ExtensionsLoaderTests.cs).
(Also thank you to the Denis, an author of AutoRest)
If still a question you can use Swagger Parser library:
https://github.com/swagger-api/swagger-parser
as simple as:
// parse a swagger description from the petstore and get the result
SwaggerParseResult result = new OpenAPIParser().readLocation("https://petstore3.swagger.io/api/v3/openapi.json", null, null);

Cloud Endpoints not accepting JSON array

I want to build my endpoint, which accept JSON array of below format:
[
{
"test":"Math",
"result":"Pass"
},
{
"test":"Science",
"result":"FirstClass"
}
]
It will be a POST call with the above JSON to my endpoint.
I tried it with servlet too but did not get the required result, and also tried to with list and inserting in a new class and posting to that class. Thanks in advance.
Is that an accurate representation of the JSON object which is being sent over? Because one does not simply send a a POST request with a JSON object of their param object to a cloud endpoint. See here for a thorough guide to Endpoint API interaction from a javascript perspective - notice how the client library exposes an object "gapi" through which calls are made. If you're sending this JSON from an iOS or Android app, there are similar client libraries which can be generated for you by a cloud endpoints build tool.
After much frustration, I resorted to reading the docs more carefully. In that quest, I found an important note in the doc:
https://cloud.google.com/endpoints/docs/frameworks/java/parameter-and-return-types
"Any type except a parameter or injected type is considered an entity type. ... Entity types cannot be annotated with #Named"
With all examples showing named parameters, I was stumped as the docs don't explain further, but then found a solution. It ends up that if you do not have named parameters, everything is just passed in as a LinkedHashMap. Usually, you can do any work you need to with just that data structure, but if you HAVE to have it in JSON, you can convert it. Here are some examples:
#ApiMethod(name = "endpointIterfaceName.createItems", httpMethod = "post", path = "test/items")
public WhateverReturnType createItems(LinkedHashMap<String, Object> itemsMap) {
// Do Stuff with map values
return whateverReturnValue;
}
With this, you need to be sure that you post your data with the Content-Type of json (i.e. Content-Type:application/json; charset=UTF-8). So, for example, when testing, with a jquery ajax call you would need to set dataType to "json" or with Postman, you would select "Raw" then JSON (application/json).
If you really want to convert this to a JSON object in Java because for whatever reason you can not use a hash map, you can do the following in your method:
// Use gson library to convert the map to a string
Gson gson = new Gson();
String mapAsJsonString = gson.toJson(itemsMap);
// create a JSON object from the new string representation
JSONObject obj = new JSONObject(mapAsJsonString);
As a side note, if this is passed as Content-Type:text then the whole body will be in the map as the first key of the map. You could do some inadvisable things here and just get that key and avoid converting the map to a string and then to a json object, but, like I said, that is inadvisable. :)

Resteasy: How does json extension get extracted from /customers.json

I don't understand how the below class is able to recognize the request /customers.json as the /customers path and able to extract and extract the json extension. There is no path parameters.
"Consider this
JAX-RS resource class:
#Path("/customers")
public class CustomerResource
{
#GET
#Produces("application/xml")
public Customer getXml() {...}
#GET
#Produces("application/json")
public Customer getJson() {...}
}
For this CustomerService JAX-RS resource class, if a request of GET /custom
ers.json came in, the JAX-RS implementation would extract the .json suffix and remove
it from the request path. It would then look in its media type mappings for a media
type that matched json. In this case, let’s say json mapped to application/json. It
would use this information instead of the Accept header and dispatch this request to
the getJson() method."
I got the official answer from author: "The specification does not define a facility for this, but most JAX-RS implementations support it."

Resources