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

Add a Positioned type to fix RawValue error position. #933

Open
wants to merge 3 commits into
base: master
Choose a base branch
from

Conversation

maartendeprez
Copy link

RawValue can be used to defer parsing until later, but errors reported during the second parsing step will report line and column numbers relative to the start of the RawValue, not to the start of the actual input. This is unhelpful and confusing to users unaware of the inner workings of the deserialization process.

This pull request add a Positioned type that can be wrapped around any other deserializable type to save the position in the input stream, and a PositionedRead type to allow deserializing from Positioned while fixing reported line and column numbers.

This can be used as follows (with the raw_value feature enabled):

use serde::{Deserialize, Serialize};
use serde_json::{value::RawValue, Positioned};

#[derive(Serialize, Deserialize)]
#[serde(bound(deserialize = "'de: 'a"))]
struct DynamicContainer<'a> {
    inner: Positioned<&'a RawValue>,
    fixed: String,
}

#[derive(Serialize, Deserialize)]
struct StaticContainer {
    inner: Inner,
    fixed: String,
}

#[derive(Serialize, Deserialize)]
struct Inner {
    one: String,
    another: String,
}

fn main() {
    let input = r#"{
                "fixed": "Test",
                "inner": {
                        "one": ["oops"]
                }
        }"#;

    let dynamic: DynamicContainer = serde_json::from_str(input).unwrap();
    let inner_decode_err =
        Inner::deserialize(&mut serde_json::Deserializer::new(dynamic.inner.read()))
            .err()
            .unwrap();
    let static_decode_err = serde_json::from_str::<StaticContainer>(input)
        .err()
        .unwrap();

    println!("static: {}", static_decode_err);
    println!("dynamic: {}", inner_decode_err);
}

Without Positioned this would report an incorrect position for the error during the two-step deserialization:

static: invalid type: sequence, expected a string at line 4 column 10
dynamic: invalid type: sequence, expected a string at line 2 column 10

With the Positioned inner deserialization step, this correctly reports the error position:

static: invalid type: sequence, expected a string at line 4 column 10
dynamic: invalid type: sequence, expected a string at line 4 column 10

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

1 participant