Passing object as array in body in proto3 - grpc

I'm wondering how I can pass an array as the body of the message without having to specify a key. I can easily do:
message TypeResponse {
message Type {
string ID = 1;
string Name = 2;
string Description = 3;
string IsMobile = 4;
string IsTablet = 5;
string IsDesktop = 6;
}
repeated Type types = 1;
}
That would response with:
{
"types": [
{
"ID": 1
...
}
]
}
I'd like to structure my response as the following to match my REST API:
[
{
"ID": 1
...
},
{
"ID": 2
...
}
]

Proto requires that the top level concept is a message, which spills into the JSON mapping.
Something you could do is just skip the first characters until you reach a [ character, and then drop the very last character which will be a ]. The output format for JSON is specified by the Proto3 spec, so you can reasonably depend on the format.

Related

Google DLP userdefined output for sensitive data

I'm having this request body for Google DLP as a text value. Is there any way to configure userdefined RedactConfig to modify the output..?. Is there any way to achieve that one..?
{
"item":{
"value":"My name is Alicia Abernathy, and my email address is aabernathy#example.com."
},
"deidentifyConfig":{
"infoTypeTransformations":{
"transformations":[
{
"infoTypes":[
{
"name":"EMAIL_ADDRESS"
}
],
"primitiveTransformation":{
"replaceWithInfoTypeConfig":{
}
}
}
]
}
},
"inspectConfig":{
"infoTypes":[
{
"name":"EMAIL_ADDRESS"
}
]
}
}
Is there any way to configure userdefined RedactConfig to modify the output..?
And I need the following O/P from Google DLP.
{
"item": {
"value": "My name is Alicia Abernathy, and my email address is {{__aabernathy#example.com__[EMAIL_ADDRESS]__}}."
},
"overview": {
"transformedBytes": "22",
"transformationSummaries": [
{
"infoType": {
"name": "EMAIL_ADDRESS"
},
"transformation": {
"replaceWithInfoTypeConfig": {}
},
"results": [
{
"count": "1",
"code": "SUCCESS"
}
],
"transformedBytes": "22"
}
]
}
}
So you don't actually want to anonymize text, you just want to add information to it? This API isn't suitable for that ... your best bet is to just use inspectContent and with the byte offsets in the findings do your own transforms.
Something like this in pseudocode ...
private static final void labelStringWithFindings(
String stringToLabel,
InspectContentResponse dlpResponse) {
StringBuilder output = new StringBuilder();
final byte[] messageBytes = ByteString.copyFromUtf8(
stringToLabel).toByteArray();
ImmutableList sortedFindings =
sort(dlpResponse.getResult().getFindingsList());
int lastEnd = 0;
for (Finding finding : sortedFindings) {
String quote = Ascii.toLowerCase(finding.getQuote());
String infoType = finding.getInfoType().getName();
String surrogate = String.format("{{__%s__[%s]__}}",
quote, infoType);
final byte[] surrogateBytes = surrogate.getBytes(StandardCharsets.UTF_8);
int startIndex = (int) finding.getLocation().getByteRange().getStart();
int endIndex = (int) finding.getLocation().getByteRange().getEnd();
if (lastEnd == 0 || startIndex > lastEnd) {
output.write(messageBytes, lastEnd, startIndex - lastEnd);
output.write(surrogateBytes, 0, surrogate.length);
}
if (endIndex > lastEnd) {
lastEnd = endIndex;
}
}
if (messageBytes.length > lastEnd) {
output.write(messageBytes, lastEnd, messageBytes.length - lastEnd);
}
return output.toString();
}

Pacts: Matching rule for non-empty map (or a field which is not null) needed

I need help with writing my consumer Pacts using pact-jvm (https://github.com/DiUS/pact-jvm).
My problem is I have a field which is a list (an array) of maps. Each map can have elements of different types (strings or sub-maps), eg.
"validatedAnswers": [
{
"type": "typeA",
"answers": {
"favourite_colour": "Blue",
"correspondence_address": {
"line_1": "Main St",
"postcode": "1A 2BC",
"town": "London"
}
}
},
{
"type": "typeB",
"answers": {
"first_name": "Firstname",
"last_name": "Lastname",
}
}
]
but we're only interested in some of those answers.
NOTE: The above is only an example showing the structure of validatedAnswers. Each answers map has dozens of elements.
What we really need is this: https://github.com/pact-foundation/pact-specification/issues/38, but it's planned for v.4. In the meantime we're trying a different approach. What I'm attempting to do now is to specify that each element of the list is a non-empty map. Another approach is to specify that each element of the list is not null. Can any of this be done using Groovy DSL?
This:
new PactBuilder().serviceConsumer('A').hasPactWith('B')
.port(findAvailablePort()).uponReceiving(...)
.willRespondWith(status: 200, headers: ['Content-Type': 'application/json'])
.withBody {
validatedAnswers minLike(1) {
type string()
answers {
}
}
}
doesn't work because it mean answers is expected to be empty ("Expected an empty Map but received Map( [...] )", see also https://github.com/DiUS/pact-jvm/issues/298).
So what I would like to do is something like this:
.withBody {
validatedAnswers minLike(1) {
type string()
answers Matchers.map()
}
}
or:
validatedAnswers minLike(1) {
type string()
answers {
keyLike 'title', notNull()
}
}
or:
validatedAnswers minLike(1) {
type string()
answers notNull()
}
Can it be done?
I would create two separate tests for this, one test for each of the different response shapes and have a provider state for each e.g. given there are type b answers.
This way when you verify on provider side, it will only send those two field types.
The union of the two examples gives a contract that allows both.
You can do it without DSL, sample Groovy script:
class ValidateAnswers {
static main(args) {
/* Array with some samples */
List<Map> answersList = [
[
type: 'typeA',
answers: [
favourite_colour: 'Blue',
correspondence_address: [
line_1: 'Main St',
postcode: '1A 2BC',
town: 'London'
]
]
],
[
type: 'typeB',
answers: [
first_name: 'Firstname',
last_name: "Lastname"
]
],
[
type: 'typeC',
answers: null
],
[
type: 'typeD'
],
[
type: 'typeE',
answers: [:]
]
]
/* Iterating through all elements in list above */
for (answer in answersList) {
/* Print result of checking */
println "$answer.type is ${validAnswer(answer) ? 'valid' : 'not valid'}"
}
}
/**
* Method to recursive iterate through Map's.
* return true only if value is not an empty Map and it key is 'answer'.
*/
static Boolean validAnswer(Map map, Boolean result = false) {
map.each { key, value ->
if (key == 'answers') {
result = value instanceof Map && value.size() > 0
} else if (value instanceof Map) {
validAnswer(value as Map, false)
}
}
return result
}
}
Output is:
typeA is valid
typeB is valid
typeC is not valid
typeD is not valid
typeE is not valid

Querying Cosmos Nested JSON documents

I would like to turn this resultset
[
{
"Document": {
"JsonData": "{\"key\":\"value1\"}"
}
},
{
"Document": {
"JsonData": "{\"key\":\"value2\"}"
}
}
]
into this
[
{
"key": "value1"
},
{
"key": "value2"
}
]
I can get close by using a query like
select value c.Document.JsonData from c
however, I end up with
[
"{\"key\":\"value1\"}",
"{\"key\":\"value2\"}"
]
How can I cast each value to an individual JSON fragment using the SQL API?
As David Makogon said above, we need to transform such data within our app. We can do as below:
string data = "[{\"key\":\"value1\"},{\"key\":\"value2\"}]";
List<Object> t = JsonConvert.DeserializeObject<List<Object>>(data);
string jsonData = JsonConvert.SerializeObject(t);
Screenshot of result:

How can I verify that a map's values are not empty

Suppose I have a contract like this specified in groovy:
org.springframework.cloud.contract.spec.Contract.make {
request {
method "GET"
url "/api/profiles"
headers {
header('Accept': 'application/json;charset=UTF-8')
header('Content-Type': 'application/json;charset=UTF-8')
}
}
response {
status 200
headers {
header('Content-Type': 'application/json;charset=UTF-8')
}
body(
value(
stub(
'''\
[
{
"profile": "profile1",
"myMap": {}
},
{
"profile": "profile2",
"myMap": {
"12345": "FOO",
"asdf": "BAR"
}
}
]
'''
),
test(
[
[
"profile" : regex(nonEmpty()),
"myMap": [
[
??
]
]
]
]
)
)
)
}
}
Now I want to test that the map contains String to String entries where the values must not be empty. The map itself may be empty.
How can I test for dynamic key name?
On the response side of the contract you have to chose whether you're using the map notation or the string notation. If you want to do assertions on pieces of the response you have to embed those assertions inside the body or use the test matchers.
You can put the body as a multiline string and then write the testMatchers section
testMatchers{
jsonPath('$.[*].myMap', byCommand('assertKeys($it)'))
}
then it's enough for you to provide the assertion in the assertKeys method.

C# ASP.NET json objects to array

I am stuck on this error. This is my JSON data:
{
"date": "2016-08-26",
"time_of_day": "14:19",
"request_time": "2016-08-26T14:19:59+01:00",
"station_name": "Derby",
"station_code": "DBY",
"departures": {
"all": [
{
"mode": "train",
"service": "22152000",
"train_uid": "C65080"
},
{
"mode": "train",
"service": "22150000",
"train_uid": "C65145"
},
{
"mode": "train",
"service": "22180008",
"train_uid": "C70700"
}
]
}
}
What I am trying to do is add the service json object to an array, after this I want to increment through the service list and add each service to a separate API call. This is my code:
dynamic content = JsonConvert.DeserializeObject(json);
dynamic departures = content.departures;
dynamic DepartTimes = departures.all;
JArray items = ((JArray)DepartTimes["service"]);
int serviceLength = items.Count;
for (int i = 0; i < serviceLength; i++)
{
//next api call containing array increment
}
The error seems to be here :
JArray items = ((JArray)DepartTimes["service"]);
Any help is much appreciated, thank you!
One possible way is -
var json = "json";
dynamic d = JsonConvert.DeserializeObject(json);
JArray arr = new JArray();
foreach(JObject o in d.departures.all){
arr.Add(o["service"]);
}
Console.Write(arr.Count); //output : 3
Provided Json data is not proper. Second and third items must have open curly braces ({)
In addition, an example working code may be:
dynamic content = JsonConvert.DeserializeObject(json));
JArray items = (JArray)content.departures.all;
var newArray = items.Select(x=>x["service"].ToString()).ToArray();

Resources