简体   繁体   English

在Azure Logic App中反序列化ServiceBus内容

[英]Deserializing ServiceBus content in Azure Logic App

I'm trying to read the content body of a message in an Azure Logic App, but I'm not having much success. 我正在尝试在Azure Logic App中阅读邮件的内容正文,但我没有取得多大成功。 I have seen a lot of suggestions which say that the body is base64 encoded, and suggest using the following to decode: 我看到很多建议说主体是base64编码的,建议使用以下代码进行解码:

@{json(base64ToString(triggerBody()?['ContentData']))}

The base64ToString(...) part is decoding the content into a string correctly, but the string appears to contain a prefix with some extra serialization information at the start: base64ToString(...)部分正在将内容正确解码为字符串,但字符串似乎包含一个前缀,其中包含一些额外的序列化信息:

@string3http://schemas.microsoft.com/2003/10/Serialization/�3{"Foo":"Bar"}

There are also some extra characters in that string that are not being displayed in my browser. 该字符串中还有一些额外的字符未在我的浏览器中显示。 So the json(...) function doesn't accept the input, and gives an error instead. 所以json(...)函数不接受输入,而是给出错误。

InvalidTemplate. InvalidTemplate。 Unable to process template language expressions in action 'HTTP' inputs at line '1' and column '2451': 'The template language function 'json' parameter is not valid. 无法在第1行和第2451行的“HTTP”输入中处理模板语言表达式:'模板语言函数'json'参数无效。 The provided value @string3http://schemas.microsoft.com/2003/10/Serialization/ 3{"Foo":"bar" } cannot be parsed: Unexpected character encountered while parsing value: @. Path '', line 0, position 0. 提供的值@string3http://schemas.microsoft.com/2003/10/Serialization/ 3{"Foo":"bar" }无法解析: Unexpected character encountered while parsing value: @. Path '', line 0, position 0. Unexpected character encountered while parsing value: @. Path '', line 0, position 0. . Unexpected character encountered while parsing value: @. Path '', line 0, position 0. Please see https://aka.ms/logicexpressions#json for usage details.'. 有关使用详情,请参阅https://aka.ms/logicexpressions#json 。'。

For reference, the messages are added to the topic using the .NET service bus client (the client shouldn't matter, but this looks rather C#-ish): 作为参考,使用.NET服务总线客户端将消息添加到主题中(客户端应该无关紧要,但这看起来更像C#-ish):

await TopicClient.SendAsync(new BrokeredMessage(JsonConvert.SerializeObject(item)));

How can I read this correctly as a JSON object in my Logic App? 如何在Logic App中将其正确读取为JSON对象?

You can use the substring function together with indexOf and lastIndexOf to get only the JSON substring. 您可以将substring函数与indexOflastIndexOf一起使用,以仅获取JSON子字符串。

Unfortunately, it's rather complex, but it should look something like this: 不幸的是,它相当复杂,但看起来应该是这样的:

@json(substring(base64ToString(triggerBody()?['ContentData']), indexof(base64ToString(triggerBody()?['ContentData']), '{'), add(1, sub(lastindexof(base64ToString(triggerBody()?['ContentData']), '}'), indexof(base64ToString(triggerBody()?['ContentData']), '}')))))

More info on how to use these functions here . 有关如何在这里使用这些功能的更多信息。

HTH HTH

This is caused by how the message is placed on the ServiceBus, specifically in the C# code. 由消息放置在ServiceBus上的方式引起的,特别是在C#代码中。 I was using the following code to add a new message: 我使用以下代码添加新消息:

var json = JsonConvert.SerializeObject(item);
var message = new BrokeredMessage(json);
await TopicClient.SendAsync(message);

This code looks fine, and works between different C# services no problem. 这段代码看起来很好,并且在不同的C#服务之间工作没问题。 The problem is caused by the way the BrokeredMessage(Object) constructor serializes the payload given to it: 问题是由BrokeredMessage(Object)构造函数序列化给它的有效负载的方式引起的:

Initializes a new instance of the BrokeredMessage class from a given object by using DataContractSerializer with a binary XmlDictionaryWriter. 通过使用带有二进制XmlDictionaryWriter的DataContractSerializer,从给定对象初始化BrokeredMessage类的新实例。

That means the content is serialized as binary XML, which explains the prefix and the unrecognizable characters. 这意味着内容被序列化为二进制XML,它解释了前缀和无法识别的字符。 This is hidden by the C# implementation when deserializing, and it returns the object you were expecting, but it becomes apparent when using a different library (such as the one used by Azure Logic Apps). 在反序列化时,C#实现会隐藏它,并返回您期望的对象,但在使用不同的库(例如Azure Logic Apps使用的库)时会变得明显。

There are two alternatives to handle this problem: 有两种方法可以解决这个问题:

  • Make sure the receiver can handle messages in binary XML format 确保接收器可以处理二进制XML格式的消息
  • Make sure the sender actually uses the format we want, eg JSON. 确保发件人实际使用我们想要的格式,例如JSON。

Paco de la Cruz's answer handles the first case, using substring , indexOf and lastIndexOf : Paco de la Cruz的答案处理第一种情况,使用substringindexOflastIndexOf

@json(substring(base64ToString(triggerBody()?['ContentData']), indexof(base64ToString(triggerBody()?['ContentData']), '{'), add(1, sub(lastindexof(base64ToString(triggerBody()?['ContentData']), '}'), indexof(base64ToString(triggerBody()?['ContentData']), '}')))))

As for the second case, fixing the problem at the source simply involves using the BrokeredMessage(Stream) constructor instead. 至于第二种情况,在源处修复问题只需使用BrokeredMessage(Stream)构造函数。 That way, we have direct control over the content: 这样,我们可以直接控制内容:

var json = JsonConvert.SerializeObject(item);
var bytes = Encoding.UTF8.GetBytes(json);
var stream = new MemoryStream(bytes);
var message = new BrokeredMessage(stream, true);
await TopicClient.SendAsync(message);

Paco de la Cruz solution worked for me, though I had to swap out the last '}' in the expression for a '{', otherwise it finds the wrong end of the data segment. Paco de la Cruz解决方案对我有用,虽然我不得不将表达式中的最后一个'}'替换为'{',否则它会找到数据段的错误结尾。

I also split it into two steps to make it a little more manageable. 我还将其分为两个步骤,使其更易于管理。

First I get the decoded string out of the message into a variable (that I've called MC) using: 首先,我使用以下方法将消息中的解码后的字符串转换为变量(我称之为MC):

@{base64ToString(triggerBody()?['ContentData'])}

then in another logic app action do the substring extraction: 然后在另一个逻辑app动作中进行子串提取:

@{substring(variables('MC'),indexof(variables('MC'),'{'),add(1,sub(lastindexof(variables('MC'),'}'),indexof(variables('MC'),'{'))))}

Note that the last string literal '{' is reversed from Paco's solution. 请注意,最后一个字符串文字“{”与Paco的解决方案相反。

This is working for my test cases, but I'm not sure how robust this is. 这适用于我的测试用例,但我不确定这是多么强大。

Also, I've left it as a String, I do the conversion to JSON later in my logic app. 另外,我把它留作String,我稍后在我的逻辑应用程序中转换为JSON。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM