Format Date in response of POST rest API - rest

I create a POST API in spring boot + kotlin. I create a LocalDate object but response is something not desired. I have used
org.springframework.format.annotation.DateTimeFormat
What I get is something like:
<user>
<email>a#mail.com</email>
<lname></lname>
<fname></fname>
<birthday>
<year>2000</year>
<month>JANUARY</month>
<chronology>
<id>ISO</id>
<calendarType>iso8601</calendarType>
</chronology>
<dayOfMonth>1</dayOfMonth>
<dayOfWeek>SATURDAY</dayOfWeek>
<era>CE</era>
<dayOfYear>1</dayOfYear>
<leapYear>true</leapYear>
<monthValue>1</monthValue>
</birthday>
</user>
What I want is something like (specifically birthDay tag):
<user>
<email>a#mail.com</email>
<lname></lname>
<fname></fname>
<birthday>2000-01-01</birthday>
</user>
Here is the code:
dto class:
import org.springframework.format.annotation.DateTimeFormat
import java.time.LocalDate
#JacksonXmlRootElement
data class User (var email: String? = "",
var lname: String = "",
var fname: String = "",
#DateTimeFormat(pattern = "yyyy-MM-dd")
var birthday: LocalDate? = null)
controller class:
#RestController
#RequestMapping("/")
class Controller {
#PostMapping("/post")
fun registerByMail(#Valid body: User) : ResponseEntity<Any> {
.
.
.
var user = User(birthDay = body.birthDay)
return ResponseEntity.ok(user)
Please let me know where I doing wrong. I am making POST request using postman.
Edit : I have also tried solution mentioned here : JSON Java 8 LocalDateTime format in Spring Boot but that also doesn't worked for me.
When I use com.fasterxml.jackson.annotation.JsonFormat annotation and required dependency, I got following error:
<defaultMessage>Failed to convert value of type 'java.lang.String[]' to
required type 'java.time.LocalDate'; nested exception is
org.springframework.core.convert.ConversionFailedException: Failed to
convert from type [java.lang.String] to type
[#com.fasterxml.jackson.annotation.JsonFormat java.time.LocalDate] for value
'2000-01-01'; nested exception is java.lang.IllegalArgumentException: Parse
attempt failed for value [2000-01-01]</defaultMessage>

You have to annotate the field #field:JsonSerialize and not the property.
Beside this you have to use #JsonFormat
#JacksonXmlRootElement
data class User(
var email: String? = "",
var lname: String = "",
var fname: String = "",
#field:JsonFormat(pattern = "yyyy-MM-dd")
#field:JsonSerialize(using = LocalDateSerializer::class)
#field:JsonDeserialize(using = LocalDateDeserializer::class)
var birthday: LocalDate? = null
)
My small test:
val mapper = XmlMapper()
val xml = mapper.writeValueAsString(User(birthday = LocalDate.now()))
println(xml)
Generates the following output:
<User><email></email><lname></lname><fname></fname><birthday>2018-10-19</birthday></User>

Related

Only update values if they are not null in Koltin

So i try to only update values if they are not null in the response body of my request. This is how it looks at the moment, and if i dont send all the values with it, they just get nulled in the database. Im using Kotlin with JpaRepositories.
#PutMapping(value = ["/patient"], produces = ["application/json"])
fun updateClient(#RequestBody client: Client): ResponseEntity<Client>{
val old = repository.findById(client.id).orElseThrow{ NotFoundException("no patient found for id "+ client.id) }
val new = old.copy(lastName= client.lastName, firstName = client.firstName,
birthDate = client.birthDate, insuranceNumber = client.insuranceNumber)
return ResponseEntity(repository.save(new), HttpStatus.OK)
}
This is how the model class looks like
#Entity
data class Client(
#Id
val id: String,
val lastName: String?,
val firstName: String?,
val birthDate: Date?,
val insuranceNumber: Int?
)
Is there a easier way then writing copy once for every value and checking if its not null before?
The only thing that comes to mind that might make the process easier without modifying the current model or having to create other helper model/functions would be to use the elvis operator.
val new = old.copy(
lastName = client.lastName ?: old.lastName,
firstName = client.firstName ?: old.firstName,
birthDate = client.birthDate ?: old.birthDate,
insuranceNumber = client.insuranceNumber ?: old.insuranceNumber
)
Other ways of doing this would be to create our own copy function that would ignore input nulls, or a custom constructor that does the same. But that would require more work, and it depends on the model if that makes sense or not, for the example model that would not make sense in my opinion, it would be overkill

Swagger / springfox generating response example automatically

Currently using springfox 2.9.2 to Swagger document an API created in Spring.
I want to add example response in the documentation, like in this image;
my understanding is that I can do something similar to this:
#ApiResponses(value = {
#ApiResponse(code = 200, message = "Success",
examples = #io.swagger.annotations.Example(
value = {
#ExampleProperty(value = "{'snapshot':{'type': 'AAA'}}", mediaType = "application/json")
}))
I'm placing this code snippet just above the GET method in this case.
unfortunately the 2 examples above always shows : identifier expected error
But I also see that I can do this too:
#ApiResponses(value = {
ApiResponse(code = 200, message = "Success", response = MyModel.class,
)
})
Also I see that I can add an example with #ApiOperation level:
#ApiOperation(value = "Create a Account", nickname = "createAccount", notes = "Create a account", response = AccountResponse.class, tags={ })
My questions are:
How can I add an example JSON response to my Swagger documentation?
It would be ideal to just point Swagger/Springfox to my model/bean and have it generate the example response automatically, and automatically update with each update for the bean/model. Is this what the second code snippet above is supposed to do?
Define example with annotation for dto:
#ApiModel("Crop")
public class CropDto {
#ApiModelProperty(name = "Unique guid", position = 1, example = "7aaee0e2-6884-4fd7-ba63-21d76723dce2")
public UUID id;
#ApiModelProperty(name = "Unique code", position = 2, example = "squ")
public String code;
#ApiModelProperty(name = "Unique name", position = 3, example = "Squash")
public String name;
#ApiModelProperty(position = 4, example = "Cucurbita pepo L.")
public String description;
}

Resolve a standalone string/file using typesafe config

I'm looking for a way to say:
val c: Config = ConfigFactory.parseString("a=fox,b=dog")
val s: String = """This is a "quick" brown ${a}.\nThat is a lazy, lazy ${b}."""
println(c.resolveString(s))
// Should print:
// > This is a "quick" brown fox.
// > That is a lazy lazy dog.
My two ideas:
Just find the placeholders with regex and replace from config one by one
convert s to config with single value and use resolveWith - but it seems quoting can be really tricky
Maybe there is an easier way?
A naive solution:
class Resolver(vars: Config) {
private lazy val placeholderRegex = "(?<=\\$\\{).*?(?=\\})".r
def resolveString(s: String): String = {
placeholderRegex.findAllIn(s).foldLeft(s) { (str, v) =>
if (vars.hasPath(v)) str.replaceAll("\\Q${" + v + "}\\E", vars.getString(v)) else str
}
}
It should be fine if the string is not huge and there are no insane numbers of distinct placeholders in it.
I have a similar situation where I automatically push elastic search index definitions before
I launch the job which uses those index definitions.
In my case the string which contains variable references is the
JSON index/template definition, which ALSO comes from the typesafe config.
(see es.template_or_index.json, below.)
I resolve these refs using the utility method I wrote on top
of apache.commons StrSubstitutor.
(see: VariableReferenceResolver.resolveReferences(String template), below)
Below is a sample of my config. Note how the property 'es.animal' is injected into the index/template json.
This can't be done with out-of-the-box features of the typesafe config library (but I think this would
be a wonderful feature for them to add !)
es {
// user and password credentials should not be checked in to git. deployer is expected to
// set these parameters into the their environment in whatever way is convenient -- .bashrc or whatever.
user = dummy
user = ${?ES_USER}
password = dummy.passwd
password = ${?ES_PASSWORD}
hostPort = "localhost:9200"
hostPort = ${?ES_HOST_PORT}
protocol = http
protocol = ${?ES_PROTOCOL}
animal = horse // This gets injected into the configuration property es.template_or_index.json
// Note: for template json there is a second round of interpolation performed so the json can reference any defined
// property of this configuration file (or anything it includes)
template_or_index {
name = test_template
json = """
{
"template": "${es.animal}_sql-*",
"settings": {
"number_of_shards": 50,
"number_of_replicas": 2
},
"mappings": {
"test_results" : {
"date_detection": false,
"properties" : {
"timestamp" : { "type" : "date"},
"yyyymmdd" : { "type" : "string", "index" : "not_analyzed"}
}
}
}
}
"""
}
}
package com.foo
import com.typesafe.config.Config;
import org.apache.commons.lang.text.StrLookup;
import org.apache.commons.lang.text.StrSubstitutor;
public class VariableReferenceResolver {
final StrSubstitutor substitutor;
static class ConfigStrLookup extends StrLookup {
private final Config config;
ConfigStrLookup(Config config) {
this.config = config;
}
public String lookup(String key) {
return config.getString(key);
}
}
public VariableReferenceResolver (Config config) {
substitutor=new StrSubstitutor(new ConfigStrLookup(config));
}
public String resolveReferences(String template) {
return substitutor.replace(template);
}
}
public class OtherClass {
private static void getIndexConfiguration(String path) throws IOException {
System.setProperty("config.file", path);
Config config = ConfigFactory.load();
String user = config.getString("es.user");
String password = config.getString("es.password");
String protocol = config.getString("es.protocol");
String hostPort = config.getString("es.hostPort");
String indexOrTemplateJson = config.getString("es.template_or_index.json");
String indexOrTemplateName = config.getString("es.template_or_index.name");
VariableReferenceResolver resolver = new VariableReferenceResolver(config);
String resolvedIndexOrTemplateJson = resolver.resolveReferences(indexOrTemplateJson);
File jsonFile = File.createTempFile("index-or-template-json", indexOrTemplateName);
Files.write(Paths.get(jsonFile.getAbsolutePath()), resolvedIndexOrTemplateJson.getBytes());
curlIndexOrTemplateCreateCommand =
String.format(
"curl -XPUT -k -u %s:%s %s://%s/_template/%s -d #%s",
user, password, protocol, hostPort, indexOrTemplateName, jsonFile.getAbsolutePath());
}
....
}

Build dynamic LINQ queries from a string - Use Reflection?

I have some word templates(maybe thousands). Each template has merge fields which will be filled from database. I don`t like writing separate code for every template and then build the application and deploy it whenever a template is changed or a field on the template is added!
Instead, I'm trying to define all merge fields in a separate xml file and for each field I want to write the "query" which will be called when needed. EX:
mergefield1 will call query "Case.Parties.FirstOrDefault.NameEn"
mergefield2 will call query "Case.CaseNumber"
mergefield3 will call query "Case.Documents.FirstOrDefault.DocumentContent.DocumentType"
Etc,
So, for a particular template I scan its merge fields, and for each merge field I take it`s "query definition" and make that request to database using EntityFramework and LINQ. Ex. it works for these queries: "TimeSlots.FirstOrDefault.StartDateTime" or
"Case.CaseNumber"
This will be an engine which will generate word documents and fill it with merge fields from xml. In addition, it will work for any new template or new merge field.
Now, I have worked a version using reflection.
public string GetColumnValueByObjectByName(Expression<Func<TEntity, bool>> filter = null, string objectName = "", string dllName = "", string objectID = "", string propertyName = "")
{
string objectDllName = objectName + ", " + dllName;
Type type = Type.GetType(objectDllName);
Guid oID = new Guid(objectID);
dynamic Entity = context.Set(type).Find(oID); // get Object by Type and ObjectID
string value = ""; //the value which will be filled with data from database
IEnumerable<string> linqMethods = typeof(System.Linq.Enumerable).GetMethods(BindingFlags.Static | BindingFlags.Public).Select(s => s.Name).ToList(); //get all linq methods and save them as list of strings
if (propertyName.Contains('.'))
{
string[] properies = propertyName.Split('.');
dynamic object1 = Entity;
IEnumerable<dynamic> Child = new List<dynamic>();
for (int i = 0; i < properies.Length; i++)
{
if (i < properies.Length - 1 && linqMethods.Contains(properies[i + 1]))
{
Child = type.GetProperty(properies[i]).GetValue(object1, null);
}
else if (linqMethods.Contains(properies[i]))
{
object1 = Child.Cast<object>().FirstOrDefault(); //for now works only with FirstOrDefault - Later it will be changed to work with ToList or other linq methods
type = object1.GetType();
}
else
{
if (linqMethods.Contains(properies[i]))
{
object1 = type.GetProperty(properies[i + 1]).GetValue(object1, null);
}
else
{
object1 = type.GetProperty(properies[i]).GetValue(object1, null);
}
type = object1.GetType();
}
}
value = object1.ToString(); //.StartDateTime.ToString();
}
return value;
}
I`m not sure if this is the best approach. Does anyone have a better suggestion, or maybe someone has already done something like this?
To shorten it: The idea is to make generic linq queries to database from a string like: "Case.Parties.FirstOrDefault.NameEn".
Your approach is very good. I have no doubt that it already works.
Another approach is using Expression Tree like #Egorikas have suggested.
Disclaimer: I'm the owner of the project Eval-Expression.NET
In short, this library allows you to evaluate almost any C# code at runtime (What you exactly want to do).
I would suggest you use my library instead. To keep the code:
More readable
Easier to support
Add some flexibility
Example
public string GetColumnValueByObjectByName(Expression<Func<TEntity, bool>> filter = null, string objectName = "", string dllName = "", string objectID = "", string propertyName = "")
{
string objectDllName = objectName + ", " + dllName;
Type type = Type.GetType(objectDllName);
Guid oID = new Guid(objectID);
object Entity = context.Set(type).Find(oID); // get Object by Type and ObjectID
var value = Eval.Execute("x." + propertyName, new { x = entity });
return value.ToString();
}
The library also allow you to use dynamic string with IQueryable
Wiki: LINQ-Dynamic

How can I deserialize an ADO.NET DataTable that contains null values using Json.NET?

I am attempting to use Newtonsoft.Json.Net35 Version 4.0.2.0 to deserialize an ADO.NET DataTable that contains null values. Serialization works fine:
[Test]
public void SerializeDataTableWithNull()
{
var table = new DataTable();
table.Columns.Add("item");
table.Columns.Add("price", typeof(double));
table.Rows.Add("shirt", 49.99);
table.Rows.Add("pants", 54.99);
table.Rows.Add("shoes"); // no price
var json = JsonConvert.SerializeObject(table);
Assert.AreEqual(#"["
+ #"{""item"":""shirt"",""price"":49.99},"
+ #"{""item"":""pants"",""price"":54.99},"
+ #"{""item"":""shoes"",""price"":null}]", json);
}
Deserialization works fine if values are missing:
[Test]
public void DerializeDataTableWithImplicitNull()
{
const string json = #"["
+ #"{""item"":""shirt"",""price"":49.99},"
+ #"{""item"":""pants"",""price"":54.99},"
+ #"{""item"":""shoes""}]";
var table = JsonConvert.DeserializeObject<DataTable>(json);
Assert.AreEqual("shirt", table.Rows[0]["item"]);
Assert.AreEqual("pants", table.Rows[1]["item"]);
Assert.AreEqual("shoes", table.Rows[2]["item"]);
Assert.AreEqual(49.99, (double)table.Rows[0]["price"], 0.01);
Assert.AreEqual(54.99, (double)table.Rows[1]["price"], 0.01);
Assert.IsInstanceOf(typeof(System.DBNull), table.Rows[2]["price"]);
}
If, however, values are explicitly null:
[Test]
public void DerializeDataTableWithExplicitNull()
{
const string json = #"["
+ #"{""item"":""shirt"",""price"":49.99},"
+ #"{""item"":""pants"",""price"":54.99},"
+ #"{""item"":""shoes"",""price"":null}]";
var table = JsonConvert.DeserializeObject<DataTable>(json);
Assert.AreEqual("shirt", table.Rows[0]["item"]);
Assert.AreEqual("pants", table.Rows[1]["item"]);
Assert.AreEqual("shoes", table.Rows[2]["item"]);
Assert.AreEqual(49.99, (double)table.Rows[0]["price"], 0.01);
Assert.AreEqual(54.99, (double)table.Rows[1]["price"], 0.01);
Assert.IsInstanceOf(typeof(System.DBNull), table.Rows[2]["price"]);
}
DeserializeObject throws "System.ArgumentException : Cannot set Column 'price' to be null. Please use DBNull instead." The following workaround works for my particular JSON:
var regex = new Regex(#",?""[_\w]+"":null");
var nullless = regex.Replace(json, string.Empty);
var table = JsonConvert.DeserializeObject<DataTable>(nullless);
but like all regular expression-based kludges this is clearly brittle.
Finally, the questions:
Is this a bug?
Json.NET has many events that can be hooked. Is there a way to get notified when a when a null value is encountered and explicitly set the value to System.DBNull?
Thanks in advance,
Frank
It looks like this is a bug which is easily fixed by replacing
dr[columnName] = reader.Value
with
dr[columnName] = reader.Value ?? System.DBNull.Value
in Newtonsoft.Json.Converters.DataTableConverter. I have entered an issue in the tracker.