I am using .Net 6 WebAPI. I need to accept a generic JSON array as input. The properties present in each JSON document is not known before. So I cannot Deserialize to specific object type. So I am looking for 2 inputs.
a) What should be input datatype to accept this in body, when using System.Text.Json? Previously, we have used JArray using JSON.NET.
b) How can I then read this input as an array so that I can then convert into generic JsonObject type?
[
{ "prop1" : "value1", "prop2" : "value1"},
{ "prop3" : "value3", "prop4" : "value4"},
{ "propx" : "valuex", "propy" : "value6", "nested": { "other": [1,23,45] }}
]
I am also open to option of accepting NDJSON.
Thanks!
If all I do is create a new .net Web API from the standard template and add the following action:
[HttpPost]
public async Task<IActionResult> Post(JsonArray array)
{
foreach(var node in array)
{
Console.WriteLine(node);
}
return Ok();
}
And pass the content you have specified in the question using the built-in swagger UI:
And I can step through in the debugger and observe that the request has been deserialized to do what I please with:
From body you can receive ([FromBody]List<object> input) or ([FromBody]List<dynamic> input) and access to properties dynamically or serialize to typed objects.
I have a camunda bpmn workflow where the start-events required some variables.
One of the needed variable is of type 'date':
{
"variables": {
"stichtagFrist": {
"value": "2021-09-08T00:00:00",
"type": "date"
}
}
}
now trying to add a new Instance having the above mentioned json, I get the following exception:
Cannot instantiate process definition d1f43d8e-211f-11ec-8fdf-0242ac110002: Cannot convert value '2021-09-08T00:00:00' of type 'date' to java type java.util.Date"
How do I need to POST the json that Camunda can interpret it as "date" so that I can use this variable e.g. in timer-events etc.?
Are there any rules for booleans too?
https://github.com/camunda/camunda-bpm-platform/blob/7c5bf37307d3eeac3aee5724b6e4669a9992eaba/engine-rest/engine-rest/src/main/java/org/camunda/bpm/engine/rest/dto/VariableValueDto.java#L109
Uses a Jackson ObjectMapper to parse the value. It requires this format:
{
"variables": {
"stichtagFrist": {
"value": "2021-09-08T00:00:00.0+0000",
"type": "date"
}
}
}
From the documentation:
In the REST API, the type names start with a capital letter, i.e., String instead of string.
Try "Date" instead of "date", that should do the trick.
I have the following Deserializer from a Spray project that I'd like to port over to Akka-Http. I'm just starting out with Akka-Http so I'm not to sure how I can port this code:
class urlParameterEnumDeserializer[T](enum: AppEnum[T]) extends Deserializer[String, T] {
def apply(s: String) = {
enum.valueOf(s).toRight(MalformedContent(s"Expected a valid string for ${enum} conversion. Found: ${s}"))
}
}
It used to allow me to convert incoming url parameters to my application's Enum types, for instance here's an implicit function that utilizes the Deserializer:
implicit val contentSourceDeserializer = new urlParameterEnumDeserializer[ContentSource](ContentSource)
How would I accomplish the same thing in Akka-Http?
Figured this out. Akka has some pre-canned marrshallers like FromStringUnmarshaller that help out. Here's how I converted my enum Deserializer to an Akka-Http UnMarshaller:
class urlParameterCrowdscriberEnumDeserializer[T](enum: CrowdscriberEnum[T]) extends FromStringUnmarshaller[T] {
override def apply(s: String)(implicit ec: ExecutionContext, materializer: Materializer): Future[T] = {
enum.valueOf(s) match {
case Some(e) => FastFuture.successful(e)
case None => FastFuture.failed(new IllegalArgumentException(s"Expected a valid string for ${enum} conversion. Found: ${s}"))
}
}
}
I'm trying to understand the behaviour of DataWeave v1.0 when it comes to mapping objects in a root JSON array.
At this stage I just want to map each item in the array as-is without mapping each individual field of the item. I need to do it for each item in the array because later on I want to edit some of the fields, but since there are potentially many I don't want the overhead of mapping them one-by-one.
This is my dataweave:
%dw 1.0
%output application/json
---
payload map {
($)
}
This is my input:
[
{
"MyString": "ABCD",
"MyNumber": 123,
"AnObject": {
"MyBool": false,
"MyNestedObject": {
"MyNestedString": "DEF"
}
}
}
]
I want my output to be (at this stage) exactly the same as my input.
Instead my (wrong) output is:
[
{
"MyString": "ABCD",
"MyNumber": 123,
"MyBool": false,
"MyNestedObject": {
"MyNestedString": "DEF"
}
}
]
As you can see the object AnObject is missing, although its children remain.
Things are worse if the input includes arrays, for example the input:
[
{
"MyString": "ABCD",
"MyNumber": 123,
"AnObject": {
"MyBool": false,
"MyNestedObject": {
"MyNestedString": "DEF"
}
},
"AnArray": [
{
"Title": "An array item",
"Description": "Pretty standard"
}
]
}
]
Throws the error:
Cannot coerce a :array to a :object.
I have played around with the mapObject operation on the root array items too, but I always run into the same behaviour. Is anyone able to explain what is happening here, and show me how I can copy each item in the root payload across dynamically.
Mule runtime is 3.9.1.
To go through each item in the array and let them as it is, you should do payload map $, that is the same as payload map ((item) -> item)
What you were doing is the same as: payload map ((item) -> {(item)}).
Here what you are returning for each item is the expression {(expr)} that in the DW version that runs on Mule 3.9.1, it has an accidental behavior where the expression tries to coerce expr (that in this case is an object) to array of objects and then it will try to flatten all the objects in that coerced array inside the parent object. It looks like is trying to coerce the value of the keys too, that's why DW throws the error.
This behavior of {()} changes in newer versions of DW.
Using Spring Data REST with JPA in version 2.0.2.RELEASE.
How can I disable Hypertext Application Language (HAL) in the JSON ? http://stateless.co/hal_specification.html
I have tried many things already, but to no avail. For example, I have set Accept and Content-type headers to "application/json" instead of "application/hal+json" but I still receive the JSON content with hyper links.
For example, I'd like to get something like:
{
"name" : "Foo",
"street" : "street Bar",
"streetNumber" : 2,
"streetLetter" : "b",
"postCode" : "D-1253",
"town" : "Munchen",
"country" : "Germany",
"phone" : "+34 4410122000",
"vat" : "000000001",
"employees" : 225,
"sector" : {
"description" : "Marketing",
"average profit": 545656665,
"average employees": 75,
"average profit per employee": 4556
}
}
Instead of:
{
"name" : "Foo",
"street" : "street Bar",
"streetNumber" : 2,
"streetLetter" : "b",
"postCode" : "D-1253",
"town" : "Munchen",
"country" : "Germany",
"phone" : "+34 4410122000",
"vat" : "000000001",
"employees" : 225,
"_links" : {
"self" : {
"href" : "http://localhost:8080/app/companies/1"
},
"sector" : {
"href" : "http://localhost:8080/app/companies/1/sector"
}
}
}
Thanks for your help.
(Hyper)media types
The default settings for Spring Data REST use HAL as the default hypermedia representation format, so the server will return the following for the given Accept headers:
No header -> application/hal+json -> HAL
application/hal+json -> application/hal+json -> HAL
application/json -> application/json -> HAL (this is what the default configures)
application/x-spring-data-verbose+json -> application/x-spring-data-verbose+json -> a Spring Data specific format (using links for the links container and content as wrapper for the collection items.
If you configure RepositoryRestConfiguration.setDefaultMediaType(…) to a non-HAL format, the server will return the Spring Data specific JSON format unless you explicitly ask for application/hal+json. Admittedly the configuration option is probably a bit misleading, so I filed DATAREST-294 to improve this. The issue was resolved in 2.1 RC1 (Dijkstra) 2014.
Note that we effectively need a hypermedia format in place to be able to express relations between managed resources and enable discoverability of the server. So there's no way you'll be able to get rid of it completely. This is mostly due to the fact that you could easily crash the server if you expose entities that have bidirectional relationships or make up an enormous object graph.
Inlining related entities
If you never want to have sectors linked to and always inline them, one option is to simply exclude the SectorRepository from being exported as a REST resource in the first place. You can achieve this by annotating the repository interface with #RepositoryRestResource(exported = false).
To get a representation returned as you posted in your lower example have a look at the projections feature introduced in Spring Data REST 2.1 M1. It basically allow you to craft optional views on a resource that can differ from the default one via a simple interface.
You'd basically define an interface:
#Projection(name = "foo", types = YourDomainClass.class)
interface Inlined {
// list all other properties
Sector getSector();
}
If you either put this interface into a (sub)package of your domain class or manually register it via RepositoryRestConfiguration.projectionConfiguration() the resources exposing YourDomainClass will accept a request parameter projection so that passing in foo in this example would render the inlined representation as you want it.
This commit has more info on the feature in general, this commit has an example projection defined.
So you want 2 things:
1) get rid of _links field
2) include the related sector field
Possible solution (works for me :D)
1) get rid of _links
For this create the class below:
[... package declaration, imports ...]
public class MyRepositoryRestMvcConfiguration extends RepositoryRestMvcConfiguration {
public MyRepositoryRestMvcConfiguration(ApplicationContext context, ObjectFactory<ConversionService> conversionService) {
super(context, conversionService);
}
#Bean
protected LinkCollector linkCollector() {
return new LinkCollector(persistentEntities(), selfLinkProvider(), associationLinks()) {
public Links getLinksFor(Object object, List<Link> existingLinks) {
return new Links();
}
};
}
}
and use it e.g.:
[... package declaration, imports ...]
#SpringBootApplication
#Import({MyRepositoryRestMvcConfiguration.class})
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}
I'm pretty sure (99%, but not tested) that you won't need this class for removing the _links for the related entity/entities included the way next point (2) is showing.
2) include the related sector field
For this you could use Excerpts (especially made for this scenario). Because the Spring example is so eloquent and it's silly to just copy it here I'll just point it: https://docs.spring.io/spring-data/rest/docs/3.1.x/reference/html/#projections-excerpts.excerpting-commonly-accessed-data.
But just for the record and your convenience I'll paste the main parts of the spring example:
#Projection(name = "inlineAddress", types = { Person.class })
interface InlineAddress {
String getFirstName();
String getLastName();
Address getAddress();
}
see at Projection javadoc that types means The type the projection type is bound to.
The excerpt could be used this way:
#RepositoryRestResource(excerptProjection = InlineAddress.class)
interface PersonRepository extends CrudRepository<Person, Long> {}
in order to get this (when also using MyRepositoryRestMvcConfiguration):
{
"firstName" : "Frodo",
"lastName" : "Baggins",
"address" : {
"street": "Bag End",
"state": "The Shire",
"country": "Middle Earth"
}
}
For you the sector is the equivalent of address.
Final notes
When returning arrays the _links field won't be removed (it's too intrusive to do it); in the end you'll have something like this:
{
"_embedded" : {
"persons" : [ {person1}, {person2}, ..., {personN} ]
},
"_links" : {
e.g. first, next, last, self, profile
},
"page" : {
"size" : 1,
"totalElements" : 10,
"totalPages" : 10,
"number" : 0
}
}
As you can see even if we'd have _links removed that still won't be enough; one would probably also want _embedded replaced by persons which would lead to less maintainable code (too much spring intrusive overrides). But if one really wants these too he should start checking RepositoryRestMvcConfiguration and RepositoryEntityController.getCollectionResource.
Spring is evolving so I feel the need to point that this works with at least:
spring-data-rest-webmvc 3.1.3.RELEASE
or, if you prefeer spring boot version:
spring-boot-starter-parent 2.1.1.RELEASE
If you want to delete _links do the following (worked for me):
Go to your pom.xml and delete the following dependency:
spring-boot-starter-data-rest
Make an "Update project" to update the pom.xml changes.
Now it will be use your own controller for the api rest, deleting _self, _links..., that alike this:
[... package declaration, imports ...]
#RestController
#RequestMapping("/series")
public class SerieController {
#Autowired
private SerieRepositorio serieRepositorio;
public SerieController(SerieRepositorio serieRepositorio) {
this.serieRepositorio = serieRepositorio;
}
#GetMapping
public Iterable<Serie> getAllSeries() {
return serieRepositorio.findAll();
}
}