Skip to content
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

Fix JSON parsing bug for modeled empty structs #683

Merged
merged 4 commits into from
Sep 2, 2021
Merged

Fix JSON parsing bug for modeled empty structs #683

merged 4 commits into from
Sep 2, 2021

Conversation

jdisanti
Copy link
Collaborator

@jdisanti jdisanti commented Sep 1, 2021

Motivation and Context

This will fix aws-sdk-rust#212.

Testing

  • Reproduced the issue with the following:
#[tokio::main]
async fn main() {
    tracing_subscriber::fmt::init();

    let resp = http::Response::builder()
        .status(200)
        .body(
            r#"
            {"scheduleActions":[{"actionName":"REDACTED","scheduleActionStartSettings":
            {"immediateModeScheduleActionStartSettings":{"time":"2021-08-29T21:54:42.651"}},
            "scheduleActionSettings":{"inputSwitchSettings":
            {"inputAttachmentNameReference":"REDACTED","urlPath":[]}}}]}
            "#,
        )
        .unwrap();

    let _schedule = DescribeSchedule::new()
        .parse_loaded(&resp.map(Bytes::from))
        .unwrap();
}
  • Also reproduced the issue in the JsonParserGeneratorTest.
  • Added rest-json-extras test case.
  • Verified all work correctly after code fix.

Checklist

  • I have updated the CHANGELOG

By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.

@jdisanti
Copy link
Collaborator Author

jdisanti commented Sep 1, 2021

@jdisanti jdisanti requested a review from rcoh September 1, 2021 23:01
return
} else {
rustTemplate("#{expect_start_object}(tokens.next())?;", *codegenScope)
}
objectKeyLoop {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if we actually put the members.isEmpty check inside of objectKeyLoop, I think we can remove the special casing and the other changes around consuming vs. not consuming the start element? It also makes it a little clearer and more consistent IMO.

Am I correct in saying that if we fully removed the members.isEmpty() branch the code would be correct (but maybe it would fail a clippy check?)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if we actually put the members.isEmpty check inside of objectKeyLoop, I think we can remove the special casing and the other changes around consuming vs. not consuming the start element? It also makes it a little clearer and more consistent IMO.

I think overall, it's simpler, but it does require the introduction of a skip_to_end variation of skip_value that assumes the start object/array has already been consumed.

Am I correct in saying that if we fully removed the members.isEmpty() branch the code would be correct (but maybe it would fail a clippy check?)

Yeah, that's correct.

@jdisanti
Copy link
Collaborator Author

jdisanti commented Sep 2, 2021

There's no codegen diff now for the smoketest services since the only difference is for modeled empty structs, and none of them have any. Here's an example of generated code for a modeled empty struct though:

pub fn deser_structure_empty_struct<'a, I>(
    tokens: &mut std::iter::Peekable<I>,
) -> Result<Option<crate::model::EmptyStruct>, smithy_json::deserialize::Error>
where
    I: Iterator<
        Item = Result<smithy_json::deserialize::Token<'a>, smithy_json::deserialize::Error>,
    >,
{
    match tokens.next().transpose()? {
        Some(smithy_json::deserialize::Token::ValueNull { .. }) => Ok(None),
        Some(smithy_json::deserialize::Token::StartObject { .. }) => {
            #[allow(unused_mut)]
            let mut builder = crate::model::EmptyStruct::builder();
            smithy_json::deserialize::token::skip_to_end(tokens)?;
            Ok(Some(builder.build()))
        }
        _ => Err(smithy_json::deserialize::Error::custom(
            "expected start object or null",
        )),
    }
}

@jdisanti jdisanti merged commit d770c03 into smithy-lang:main Sep 2, 2021
@jdisanti jdisanti deleted the fix-medialive-json branch September 2, 2021 18:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants