-
Notifications
You must be signed in to change notification settings - Fork 27
Updates the MessageSerializer to store the json value as the actual json object in the data field.Update data field serialization
#193
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
| "Projects": [ | ||
| { | ||
| "Name": "AWS.Messaging", | ||
| "Type": "Patch", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this should be a Minor because there is a significant change in behavior. I would call that out as a breaking change.
src/AWS.Messaging/MessageEnvelope.cs
Outdated
| /// The data content type. | ||
| /// </summary> | ||
| [JsonPropertyName("datacontenttype")] | ||
| public string? DataContentType { get; set; } = null!; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why do you need to explicitly set it to null!? The default for string? is null.
|
|
||
| /// <summary> | ||
| /// Deserializes the raw string message into the .NET type. | ||
| /// Deserializes a JsonElement message into the specified .NET type. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
add a doc ref for JsonElement
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed this and other comments in latest revision
| /// <param name="message">The string message that will be deserialized.</param> | ||
| /// <param name="deserializedType">The .NET type that represents the deserialized message.</param> | ||
| object Deserialize(string message, Type deserializedType); | ||
| /// <param name="message">The JsonElement containing the message to be deserialized.</param> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same here
| { | ||
| return (T)Deserialize(message, typeof(T)); | ||
| } | ||
| string DataContentType { get; } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Isn't this always "application/json"? How else are we initializing this to a diff val?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
for our message serializer it will always be application/json.
| /// <inheritdoc/> | ||
| /// <exception cref="FailedToDeserializeApplicationMessageException"></exception> | ||
| /// <summary> | ||
| /// Deserializes a JsonElement message into the specified type. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
add doc ref to JsonElement
| /// <summary> | ||
| /// Deserializes a JsonElement message into the specified type. | ||
| /// </summary> | ||
| /// <param name="message">The JsonElement containing the message to deserialize.</param> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same here
|
|
||
| // Deserialize the message content using the custom serializer | ||
| var dataContent = JsonPropertyHelper.GetRequiredProperty(root, "data", element => element.GetString()!); | ||
| var dataContent = JsonPropertyHelper.GetRequiredProperty(root, "data", element => element); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we make this resilient to support the data being either JSON or escaped JSON? I know we are in preview and can make breaking changes but I'm concerned how we are going to roll out this change. If we can make it resilient at least on the reading side that can help.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm. Is there a reason we would want to support both? The correct behavior per the cloudspec is the new logic and feel like since we are still in preview this is the time to make the breaking change. I feel it would complicate the code to support both
d522cf6 to
e56fc52
Compare
1ab1168 to
2bc86b2
Compare
| ["time"] = envelope.TimeStamp, | ||
| ["data"] = _messageSerializer.Serialize(message) | ||
| ["datacontenttype"] = _messageSerializer.DataContentType, | ||
| ["data"] = JsonNode.Parse(_messageSerializer.Serialize(message)) // parse the string to get the value as the actual json node. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this makes the assumption that the user's implementation of message serializer will always return json, which i think is fine for now ( unless are we expecting customers to want to do xml serialization or other things)? Otherwise we have to add more logic in EnvelopeSerializer to handle the case where its not json type for serializing/deserializing like
if isDataContentJson(datacontenttype)
data = JsonNode.Parse(_messageSerializer.Serialize(message))
else
data = _messageSerializer.Serialize(message)
private isDataContentJson()
{
// some way to determine if its json
}
and then in deserialization we would have to do the reverse. If we are fine with this logic being inside EnvelopeSerializer then i can add it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
also @normj responding to your other comment here #193 (comment) - having a flag to turn on and off for parsing as well would be a similar implementation. so wondering how strongly you feel about that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we should assume the content return is JSON. Should we have the MessageSerializer's serialize method return back a results type that includes the serialized message and the content type? Then the envelople serializer can look at the content type and decide what to do based on the content type?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
return back a results type that includes the serialized message and the content type? Then the envelope serializer can look at the content type and decide what to do based on the content type?
im fine with this. i think thats the best way we are going to figure out. i will update the code
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've updated it in the latest revision to have a check in EnvelopeSerializer. And i retested both scenarios manually.
- Retested with application/json - data gets stored as the actual json object
- Retested with application/plain as the data content type, the data gets stored as the string value. i manually edited our messageserializer and changed the datacontenttype to application/plain to test
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
application/json
{
"version": "0",
"id": "a4579b24-b741-cc2e-df7d-eec8f890da27",
"detail-type": "Payload",
"source": "/aws/messaging",
"account": "147997163238",
"time": "2025-03-31T17:33:28Z",
"region": "us-east-1",
"resources": [],
"detail": {
"id": "b08c718c-e63d-4547-9790-030025689103",
"source": "/aws/messaging",
"specversion": "1.0",
"type": "Payload",
"time": "2025-03-31T17:33:27.1657903+00:00",
"datacontenttype": "application/json",
"data": {
"Id": "036f7898-3e03-403a-b4f6-f18227310330",
"Name": "Test",
"SomeValue": 42
}
}
}
application/plain
{
"version": "0",
"id": "80f21c60-9797-d928-d0e1-af78e0f7dcba",
"detail-type": "Payload",
"source": "/aws/messaging",
"account": "147997163238",
"time": "2025-03-31T17:39:49Z",
"region": "us-east-1",
"resources": [],
"detail": {
"id": "0695f334-bb82-4f03-be12-154cb892b172",
"source": "/aws/messaging",
"specversion": "1.0",
"type": "Payload",
"time": "2025-03-31T17:39:47.7147488+00:00",
"datacontenttype": "application/plain",
"data": "{\"Id\":\"4a6f1d73-289d-4632-88b0-a79318961a25\",\"Name\":\"Test\",\"SomeValue\":42}"
}
}
2bc86b2 to
f9da426
Compare
|
|
||
| if (IsJsonContentType(envelope.DataContentType)) | ||
| { | ||
| blob["data"] = JsonNode.Parse(_messageSerializer.Serialize(message)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was thinking instead of having a global DataContentType for the IMessageSerializer. The Serialize method would return back the content type. That way you could implement different message content type based on the message type.
I think that would mean the MessageEnvelope<T> from CreateEnvelopeAsync would leave DataContentType null since it is unknown at this point. Then in SerializeAsync have something like this:
MessageSerializerResults serializationResults = _messageSerializer.Serialize(message);
var blob = new JsonObject
{
["id"] = envelope.Id,
["source"] = envelope.Source?.ToString(),
["specversion"] = envelope.Version,
["type"] = envelope.MessageTypeIdentifier,
["time"] = envelope.TimeStamp,
["datacontenttype"] = serializationResults.ContentType
};
if (IsJsonContentType(serializationResults.ContentType))
{
blob["data"] = JsonNode.Parse(serializationResults.Data);
}
else
{
blob["data"] = serializationResults.Data;
}
class MessageSerializerResults
{
public string ContentType {get;set;}
public string Data {get;set;}
}There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ah okay i see what you mean ! Yes i like that better. I will update
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
updated in last revision to have that
| Source = new Uri("/backend/service", UriKind.Relative), | ||
| Version = "1.0", | ||
| MessageTypeIdentifier = "xml", | ||
| TimeStamp = _testdate, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
removed these because testing plain/text was doing same thing
Issue #, if available: #168
Description of changes:
MessageSerializerto store the json value as the actual json object in thedatafield.datacontenttypefield to messageBefore
After
Testing
By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.