问题
I'm fairly new to Azure Functions.
I've created a C# WebHook / Azure Function (I guess that's the right thing) to take my json content and convert it into a collection of simple poco/dto objects.
public static class GenericWebHookCSharp
{
[FunctionName("GenericWebHookCsharpOne")]
public static async Task<HttpResponseMessage /* object */> Run([HttpTrigger(WebHookType = "genericJson")]HttpRequestMessage req, TraceWriter log)
{
try
{
log.Info(string.Format("C# GenericWebHookCsharpOne about to process a request. ('{0}')", DateTime.Now.ToLongTimeString()));
//IUnityContainer container = new UnityContainer();
//container.RegisterType<IJsonToPersonRequestWrapperConverter, JsonToPersonRequestWrapperConverter>();
//IJsonToPersonRequestWrapperConverter jsonConvtr = container.Resolve<IJsonToPersonRequestWrapperConverter>();
//ICollection<Person> emps = await jsonConvtr.ConvertHttpRequestMessageToPersonCollection(req);
/* above commented code is my "real" code where I take the INPUT request-body-as-json and convert it into a ICollection of Person(s) */
/* below code, I just fake-creating some persons */
string jsonContent = await req.Content.ReadAsStringAsync();
ICollection<Person> persons = new List<Person>();
for(int i = 0; i< 10; i++)
{
persons.Add(new Person() { PersonUuid = Guid.NewGuid(), LastName = "LN" + i.ToString(), FirstName = "FN" + i.ToString(), BirthDate = DateTimeOffset.Now.AddYears(-1 * (20 + i))});
}
string serializedJson = Newtonsoft.Json.JsonConvert.SerializeObject(persons);
log.Info(string.Format("C# GenericWebHookCsharpOne finished a request. ('{0}')", DateTime.Now.ToLongTimeString()));
return req.CreateResponse(HttpStatusCode.OK , serializedJson);
}
catch (Exception ex)
{
string errorMsg = ex.Message;// ExceptionHelper.GenerateFullFlatMessage(ex);
log.Error(errorMsg);
return req.CreateResponse(HttpStatusCode.BadRequest, errorMsg);
}
}
}
In another .cs file
public class Person
{
public Guid PersonUuid { get; set; }
public string LastName { get; set; }
public string FirstName { get; set; }
public DateTimeOffset? BirthDate { get; set; }
}
If I debug it in Visual Studio, it works fine.
So I added this as a step on my Logic App as seen below
So I want to add a new step that is a "for each" step. Here is what I get now: (image below). All I see is "body" from the initial trigger and the "convert" webhook function (that I have above)........
How do I get the "persons" (so I can do a for-each-person) collection to show up and be available for the next step on the Logic App?
EDIT/APPEND:
The end game is to push a service-bus-message for "each" of my Person(s).
As requested, here is the "person json".....
[{
"PersonUuid": "7ec8cc4d-831c-4c89-8516-47424ee2658d",
"LastName": "LN0",
"FirstName": "FN0",
"BirthDate": "1997-08-17T09:46:16.9839382-04:00"
},
{
"PersonUuid": "275264bc-5a86-476d-a189-512afa1e3ce4",
"LastName": "LN1",
"FirstName": "FN1",
"BirthDate": "1996-08-17T09:46:16.9844385-04:00"
},
{
"PersonUuid": "e522b827-2d2e-465d-a30a-c4b619d2e8e4",
"LastName": "LN2",
"FirstName": "FN2",
"BirthDate": "1995-08-17T09:46:16.9844385-04:00"
},
{
"PersonUuid": "f16bce36-3491-4519-bc82-580939f61b2e",
"LastName": "LN3",
"FirstName": "FN3",
"BirthDate": "1994-08-17T09:46:16.9844385-04:00"
},
{
"PersonUuid": "42456057-39ef-45aa-bd7c-ad6a8fa74fd1",
"LastName": "LN4",
"FirstName": "FN4",
"BirthDate": "1993-08-17T09:46:16.9844385-04:00"
},
{
"PersonUuid": "14088a6e-3c44-4cb0-927d-19f5eda279c4",
"LastName": "LN5",
"FirstName": "FN5",
"BirthDate": "1992-08-17T09:46:16.9844385-04:00"
},
{
"PersonUuid": "332a5cde-3cd1-467a-9dfc-2b187d6ae32e",
"LastName": "LN6",
"FirstName": "FN6",
"BirthDate": "1991-08-17T09:46:16.9844385-04:00"
},
{
"PersonUuid": "6debe134-19e6-4b16-a91d-05ded511eff6",
"LastName": "LN7",
"FirstName": "FN7",
"BirthDate": "1990-08-17T09:46:16.9844385-04:00"
},
{
"PersonUuid": "e61ef8a1-09d3-4c5b-b948-df8e0858cd29",
"LastName": "LN8",
"FirstName": "FN8",
"BirthDate": "1989-08-17T09:46:16.9844385-04:00"
},
{
"PersonUuid": "e9b27632-d3a4-4fe8-8745-04edfa8854f7",
"LastName": "LN9",
"FirstName": "FN9",
"BirthDate": "1988-08-17T09:46:16.9844385-04:00"
}]
回答1:
Ok.
I gotta get this written down before I forget. Wow, what a ride.
First the C# code on the WebHook. Note the "anonymousPersonWrapper" code.
public static class GenericWebHookCSharp
{
[FunctionName("GenericWebHookCsharpOne")]
public static async Task<HttpResponseMessage /* object */> Run([HttpTrigger(WebHookType = "genericJson")]HttpRequestMessage req, TraceWriter log)
{
try
{
log.Info(string.Format("C# GenericWebHookCsharpOne about to process a request. ('{0}')", DateTime.Now.ToLongTimeString()));
///////* below code, I just fake-creating some persons */
string jsonContent = await req.Content.ReadAsStringAsync();
ICollection<Person> persons = new List<Person>();
for (int i = 0; i < 3; i++)
{
persons.Add(new Person() { PersonUuid = Guid.NewGuid(), LastName = "LN" + i.ToString(), FirstName = "FN" + i.ToString(), BirthDate = DateTimeOffset.Now.AddYears(-1 * (20 + i)) });
}
/* the below is the "trick" to allow the for-each to work in the Logic-App. at least in my experience */
var anonymousPersonWrapper = new
{
personWrapper = persons
};
string personWrapperJsonString = JsonConvert.SerializeObject(anonymousPersonWrapper);
log.Info(string.Format("C# GenericWebHookCsharpOne finished a request. ('{0}')", DateTime.Now.ToLongTimeString()));
HttpResponseMessage returnReq = req.CreateResponse(HttpStatusCode.OK , personWrapperJsonString );
return returnReq;
}
catch (Exception ex)
{
string errorMsg = ex.Message;
log.Error(errorMsg);
return req.CreateResponse(HttpStatusCode.BadRequest, errorMsg);
}
}
}
But putting a breakpoint on "return returnReq;", I was able to see that personWrapperJsonString contained the below Json:
{
"personWrapper": [{
"PersonUuid": "31fb318d-a9bf-4c2f-ad16-0810ddd73746",
"LastName": "LN0",
"FirstName": "FN0",
"BirthDate": "1997-08-17T15:10:08.9633612-04:00"
},
{
"PersonUuid": "73fdacc7-e1e8-48ff-b161-1bd8b5f4aec1",
"LastName": "LN1",
"FirstName": "FN1",
"BirthDate": "1996-08-17T15:10:08.9633612-04:00"
},
{
"PersonUuid": "d18b4324-2d3e-41ca-9525-fe769af89e9c",
"LastName": "LN2",
"FirstName": "FN2",
"BirthDate": "1995-08-17T15:10:08.9633612-04:00"
}]
}
Ok.
Then I added a "Parse Json" action (below image)
Then I setup the Parse-Json. Below.
The above parse-json setup is not complete.
Click on the button "Use sample payload to generate schema" and that will pop a new window. Paste in your "personWrapper" json from earlier. As seen in the below image.
The above will of course create the json-schema that you need (that is for-each friendly). As seen below.
Now we're so close.
Add a For-Each (using the "More" button when you add a new step) (as seen below)
Now we setup the for-each. Looked what showed up! The "personWrapper" (below image)
For grins, I made the sessionId be the PersonUuid value (just to show that I can get hold of one of the scalar properties of the object. (image below).
And now the json as the Content of the Service Bus message. (below image)
I then published the Azure-Functions and deployed the Logic-App, and sent a request to the trigger.
Back to azure portal. The PersonUuid showed up as the SessionId! (image below)
And a quick check in Service Bus Explorer to "peek" the contents of the message (image below)
Ok, a few breadcrumbs:
I got a hint from here about putting the collection side a "wrapper".
Json.NET validate JSON array against Schema
A few errors I got along the way
"Invalid type. Expected Object but got Array."
UnsupportedMediaType "The WebHook request must contain an entity body formatted as JSON."
"this output is an array" "a foreach cannot be nested inside of another foreach"
'Json' expects its parameter to be a string or an XML.The provided value is of type 'Array.
回答2:
As Steven Van Eycken mentioned that we could parse string to array with json fucntion in the logic application. In your case we could parse the string to array in the Logic app or return jarry directly from Azure function . We can choose one of the following ways to do that . I also test it on my side, it works correctly.
In the logic App
json(body('Your action name'))
Or
Return Jarry directly in the Azure function
var jarry =JArray.Parse(Newtonsoft.Json.JsonConvert.SerializeObject(persons));
log.Info(string.Format("C# GenericWebHookCsharpOne finished a request. ('{0}')", DateTime.Now.ToLongTimeString()));
return req.CreateResponse(HttpStatusCode.OK, jarry);
来源:https://stackoverflow.com/questions/45719964/convert-json-to-poco-collection-how-to-code-a-for-each