Redzix
Redzix

Reputation: 188

Passing JSON as a string in the body of the POST request

I need a small help, because I don't know how to solve the below problem.

The requirement is simple, I have to sent the JSON to the server as a string parameter. The server basing on the key finds the mapping, and generically parses the JSON to some objects. That means, that the payload can have a different values and structures, each key has its own mapping - different data structure, number of parameters and so on. So the payload shouldn't be parsed outside the endpoint logic.

I know, that the Swagger sees the payload as a JSON, not as a string, and it tries to parse the data. How can I send the JSON as a string parameter to the endpooint without parsing the parameter? I have to parse it inside of the application, because of the mentioned mappings.

Example JSON:

{
  "key": "test",
  "payload": "[{"IDNew":1,"NameNew":"t1","DescriptionNew":"t1d", "IntegerValueNew":1, "DecimalValueNew":123.3}]"
}

When I'm trying to send the data in Swagger, I'm getting the below results:

curl -X POST "http://localhost:5110/api/InboundData" -H  "accept: */*" -H  "Content-Type: application/json-patch+json" -d "{  \"key\": \"test\", \"payload\": \"[{\"IDNew\":1,\"NameNew\":\"t1\",\"DescriptionNew\":\"t1d\", \"IntegerValueNew\":1, \"DecimalValueNew\":123.3}]\"}"

{
  "errors": {
    "payload": [
      "After parsing a value an unexpected character was encountered: I. Path 'payload', line 3, position 17."
    ]
  },
  "type": "https://tools.ietf.org/html/rfc7231#section-6.5.1",
  "title": "One or more validation errors occurred.",
  "status": 400,
  "traceId": "|d952c89f-4e25126d8cdf3697."
}

Data model:

[Required]
[JsonProperty(Required = Required.DisallowNull)]
[MaxLength(100)]
public string Key { get; set; }
       
[Required]
[JsonProperty(Required = Required.DisallowNull)]
public string Payload { get; set; }

Upvotes: 1

Views: 23743

Answers (1)

Jamshaid K.
Jamshaid K.

Reputation: 4587

The error clearly suggests that your JSON is not correct. If we analyze the payload property:

{
  "key": "test",
  "payload": "[{"IDNew":1,"NameNew":"t1","DescriptionNew":"t1d", "IntegerValueNew":1, "DecimalValueNew":123.3}]"
}

It seems you are creating a string object which further contains a JSON as a string. Generally, when you pass an array, you would pass it like this.

{
  "key": "test",
  "payload": [
    {
      "IDNew": 1,
      "NameNew": "t1",
      "DescriptionNew": "t1d",
      "IntegerValueNew": 1,
      "DecimalValueNew": 123.3
    }
  ]
}

But, since value of the payload property is not properly escaped, which is why it is not properly able to parse it as it has unexpected characters for a string value.

If you strictly want to pass a JSON Array as a string object, you need to properly escape it in order to get it working. For example below is a JSON that contains JSON as a string with properly escaped properties:

{
  "key": "test",
  "payload": "[{\"IDNew\":1,\"NameNew\":\"t1\",\"DescriptionNew\":\"t1d\", \"IntegerValueNew\":1, \"DecimalValueNew\":123.3}]"
}

This is how you would escape your JSON if you strictly want to pass a JSON object that further contains JSON as string.

Or, perhaps, use single quote (') instead for the nested JSON. For example below is a JSON that contains JSON as a string with a single quotes for the properties:

{
  "key": "test",
  "payload": "[{'IDNew':1,'NameNew':'t1','DescriptionNew':'t1d', 'IntegerValueNew':1, 'DecimalValueNew':123.3}]"
}

UPDATE

I just wanted to add a suggestion that would be less confusing and would generate an accurate output for the scenario.

It would be nice if you generate the models for your intended JSON string and serialize the model to get a JSON string then do the assignment to payload property.

var payload = new List<payloadSample1>();
payload.Add(new payloadSample1{ IDNew = 1, NameNew = "t1", DescriptionNew = "t1d" });
var payloadStr = JsonConvert.SerializeObject(payload);
// payloadStr would contain your JSON as a string.

In C#, you can also generate dynamic type objects. Use those if your JSON is constantly varying and you find it hectic to create many models for many api requests.

var payload = new List<dynamic>();
payload.Add(new { IDNew = 1, NameNew = "t1", DescriptionNew = "t1d" });
var payloadStr = JsonConvert.SerializeObject(payload);
// And even then, if you have a further JSON object to send:
var payloadParent = new { key = "test", payload = payloadStr };
// send payloadParent as your json.

This is not the cleanest approach because of many reasons one out of those would be, when there is a change in your model, you will have to manually analyze all your dynamic objects and change all the references where you are using it. But, certainly, it will reduce the confusion behind escaping and maintaining the strings.

If you are using JavaScript make the api call, then generate a proper JSON object and then stringify it to get a string.

Upvotes: 4

Related Questions