Bind complex component (JSON) automatically generates data

My JSON data is in request().body().asFormUrlEncoded().get("records")

 [{"string":"foo","termId":"793340"},{"string":"bar","termId":"460288"}] 

My definition of form:

 public static class MyForm { @Constraints.Required public List<Map<String,String>> records; public String someField; } 

It does not bind records automatically. Then I tried with POJO:

 public static class Record { public String string; public String termId; public void setString(String string) { this.string = string; } public void setTermId(String termId) { this.termId = termId; } } 

And adapted the form:

 public static class MyForm { @Constraints.Required public List<Record> records; public String someField; } 

It also does not automatically bind data. Do I really need to use low level APIs like jackson for this simple use? Any pointer? Could not find copy / paste example, and from jackson I have org.codehaus.jackson and com.fasterxml.jackson in my classpath.

UPDATE 2013-05-10: The secondary someField field has been someField to clarify that records are just one field, not the entire data structure. The answer below (I donโ€™t see the answers on these editing screens, so it doesnโ€™t matter if there is only one) works, but only with entries. Here is an example:

 private List<Record> recordsFromRequest() { String[] jsonData = request().body().asFormUrlEncoded().get("records"); Form<Record> recordDummyForm = Form.form(Record.class); Iterator<JsonNode> it = Json.parse(jsonData[0]).iterator(); List<Record> records = new ArrayList<>(); while (it.hasNext()) { records.add(recordDummyForm.bind(it.next()).get()); } return records; } 

For other form fields, as usual:

 Form<MyForm> form = play.data.Form.form(MyForm.class).bindFromRequest(); 

So, now I get to all the published form data, and my problem is solved this way (thanks!). However, this is a little ugly. I still can not figure out how to get all the data for publication in one object. If someone answers this, I will update the question and delete this part. Otherwise, I will accept one answer in a couple of days.

+6
source share
2 answers

In my opinion, you should use the jackson API as described in the official documentation here .

I assume you get JSON with request().body().asFormUrlEncoded().get() , so it returns a String[] containing your JSON string. You can do something like this (maybe a little complicated and skip Exception ):

 String[] jsonData = request().body().asFormUrlEncoded().get("records") MyForm myForm = new MyForm(); // Record should act as form, because each JSON string data contain this type Form<Record> form = Form.form(Record.class); // parse the JSON string and assign iterator Iterator<JsonNode> it = Json.parse(jsonData[0]).iterator(); // assign to the MyForm instance while (it.hasNext()) { formData.records.add(form.bind(it.next()).get()); // bind the JSON and add } 

So, at the end of the above code ((MyForm) formData).records should contain a List<Record> object from your JSON.

+2
source

I tried to reproduce your error. Therefore, I created the model as follows:

 public class EasyContact { public String someField; @Required public List<Record> records; public static class Record { public String string; public String termId; @Override public String toString() { return "Record [string=" + string + ", termId=" + termId + "]"; } } @Override public String toString() { return "EasyContact [someField=" + someField + ", records=" + records+ "]"; } } 

Then a simple controller like this:

  public static Result submit() { Form<EasyContact> filledForm = form(EasyContact.class).bindFromRequest(); Logger.info("Posted binding: " + filledForm.get().toString()); return ok(); } 

Now is the time to check:

 curl -X POST -H 'Content-Type: application/json' -d '{"someField":"didac", "records": [{"string": "string1", "termId": "111"},{"string": "string2", "termId": "222"}]}' localhost:9000/contacts 

On the playback command line, I see the correct output:

 [info] application - Posted binding: EasyContact [someField=didac, records=[Record [string=string1, termId=111], Record [string=string2, termId=222]]] 

The only error I found is when the Content-Type is not set in the request (-H ...). In this case, the structure throws an IllegalState exception.

+1
source

Source: https://habr.com/ru/post/944601/


All Articles