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

Can toJson() functionality be included as well? #1801

Open
thosakwe opened this issue Jul 14, 2018 · 8 comments · May be fixed by #2011
Open

Can toJson() functionality be included as well? #1801

thosakwe opened this issue Jul 14, 2018 · 8 comments · May be fixed by #2011
Assignees
Labels
good first issue A good starting issue for contributors (issues with this label will appear in /contribute) package:pubspec_parse type-enhancement A request for a change that isn't a bug

Comments

@thosakwe
Copy link
Contributor

It's fantastic to have an official package on Pub for parsing and extracting data from a pubspec.

There is, however, one thing, I'm wondering - would it be bad for createToJson to be true for the models contained in this package?

I'm working on updating the Angel CLI, which uses the old package:pubspec to persist changes to the project files (namely, adding dependencies the user is missing), to pubspec_parse, and if there were some way to just get a toJson method on the PubSpec.

I'll gladly send a PR, but is there is a specific reason this functionality isn't present already? I imagine there's probably a reason I didn't think about.

@kevmoo
Copy link
Member

kevmoo commented Jul 21, 2018

Hey @thosakwe

I think I avoided toJson because the pubspec is yaml – and the json output wouldn't necessarily round-trip the shape of the source.

There is quite a bit of special handling of dependencies, for instance.

If you want to take a shot, I'd accept a PR, though!

@kevmoo kevmoo added type-enhancement A request for a change that isn't a bug good first issue A good starting issue for contributors (issues with this label will appear in /contribute) labels Jul 21, 2018
@AliAkberAakash
Copy link

@kevmoo could I work on this issue?

@kevmoo
Copy link
Member

kevmoo commented Feb 5, 2023

@kevmoo could I work on this issue?

Sure! Just make sure you put in plenty of tests. I want to see that at round trips cleanly, etc.

@alestiago
Copy link

Is this being worked on? (cc: @AliAkberAakash , @kevmoo )

@AliAkberAakash
Copy link

Hey @alestiago I completely forgot about this, No it's not being worked on from my side. If you want we can work on this together.

@alestiago
Copy link

@AliAkberAakash I don't have the bandwidth right now to work on this feature. If I ever have some spare I'll let you know. If you're no longer working on this I recommend asking to get unassigned.

@mosuem mosuem transferred this issue from dart-archive/pubspec_parse Dec 20, 2024
@Levi-Lesches
Copy link
Contributor

Levi-Lesches commented Jan 3, 2025

I think I avoided toJson because the pubspec is yaml – and the json output wouldn't necessarily round-trip the shape of the source.

So I know in general that YAML is a superset of JSON, but Is there any sort of valid Pubspec that can't be represented by JSON, though? I threw this together pretty quickly -- is something like this a good starting point for a PR?

Pubspec.toJson()
import "package:pubspec_parse/pubspec_parse.dart";
import "package:pub_semver/pub_semver.dart";

extension <K, V> on Map<K, V> {
  Iterable<(K, V)> get records sync* {
    for (final entry in entries) {
      yield (entry.key, entry.value);
    }
  }
}

typedef Json = Map<String, dynamic>;

extension on Dependency {
  Json toJson() => switch (this) {
    SdkDependency(:final sdk, :final version) => {
      "sdk": sdk,
      "version": version.toString(),
    },
    HostedDependency(:final hosted, :final version) => {
      if (hosted != null) "hosted": hosted.url.toString(),
      "version": version.toString(),
    },
    GitDependency(:final url, :final ref, :final path) => {
      "git": {
        "url": url.toString(),
        if (path != null) "ref": ref,
        if (path != null) "path": path,
      },
    },
    PathDependency(:final path) => {
      "path": path.replaceAll(r'\', '/'),
    },
  };
}

extension on Pubspec {
  Json toJson() => {
    "name": name,
    "environment": {
      for (final (sdk, version) in environment.records)
        sdk: version.toString(),
    },
    if (resolution != null) "resolution": resolution,
    if (workspace != null) "workspace": workspace,
    "dependencies": {
      for (final (name, dependency) in dependencies.records)
        name: dependency.toJson(),
    },
    // ...
  };
}

That converts this

final pubspec = Pubspec("workspace",
  environment: {"sdk": Version.parse("3.6.0")},
  dependencies: {
    "http": HostedDependency(
      version: VersionRange(min: Version.parse("1.2.0"), max: Version.parse("2.0.0")),
      hosted: HostedDetails(null, Uri.parse('https://pub.dev')),
    ),
    "pub_cache_server": PathDependency(r"D:\dart\packages\pub_cache_server"),
    "flutter": SdkDependency("flutter"),
    "pubspec_parse": GitDependency(
      Uri.parse('https://github.com/Levi-Lesches/dart-lang-tools'),
      ref: 'pubspec-workspaces-1814',
      path: 'pkgs/pubspec_parse',
    ),
  },
);

into this

{
  "name": "workspace",
  "environment": {
    "sdk": "3.6.0"
  },
  "dependencies": {
    "http": {
      "hosted": "https://pub.dev",
      "version": ">1.2.0 <2.0.0"
    },
    "pub_cache_server": {
      "path": "D:/dart/packages/pub_cache_server"
    },
    "flutter": {
      "sdk": "flutter",
      "version": "any"
    },
    "pubspec_parse": {
      "git": {
        "url": "https://github.com/Levi-Lesches/dart-lang-tools",
        "ref": "pubspec-workspaces-1814",
        "path": "pkgs/pubspec_parse"
      }
    }
  }
}

Then, saving that to a file pubspec.yaml and running dart pub get in that directory works just fine:

dart pub get output
Resolving dependencies...
Downloading packages...
+ args 2.6.0
+ async 2.12.0
+ characters 1.3.0 (1.4.0 available)
+ checked_yaml 2.0.3
+ collection 1.19.0 (1.19.1 available)
+ flutter 0.0.0 from sdk flutter
+ http 1.2.2
+ http_methods 1.1.1
+ http_parser 4.1.2
+ json_annotation 4.9.0
+ material_color_utilities 0.11.1 (0.12.0 available)
+ meta 1.15.0 (1.16.0 available)
+ path 1.9.1
+ pub_cache_server 1.0.1 from path D:\dart\packages\pub_cache_server
+ pub_semver 2.1.5
+ pubspec_parse 1.5.0-wip from git https://github.com/Levi-Lesches/dart-lang-tools at d7f79e in pkgs/pubspec_parse
+ shelf 1.4.2
+ shelf_router 1.1.4
+ sky_engine 0.0.0 from sdk flutter
+ source_span 1.10.1
+ stack_trace 1.12.1
+ stream_channel 2.1.3
+ string_scanner 1.4.1
+ tar 2.0.0
+ term_glyph 1.2.2
+ typed_data 1.4.0
+ vector_math 2.1.4
+ web 1.1.0
+ yaml 3.1.3
Changed 29 dependencies!
4 packages have newer versions incompatible with dependency constraints.
Try `dart pub outdated` for more information.

It may not look like an "idiomatic" Pubspec, but in the meantime, a .toJson() would be valuable for automatically constructing and testing Pubspecs. My use case is that I'm trying to expand the test suite for package:dependency_validator and I would like to construct Pubspec objects and write them to files instead of hand-crafting multi-line strings. In terms of tests, I'm thinking just generating a bunch of Pubspec() objects and testing that Pubspec.fromJson(pubspec.toJson()) == pubspec) (which would also mean adding some notion of equality as well)

@Levi-Lesches
Copy link
Contributor

Adding the above toJson() method really helped clean up my tests. See workspace_test.dart and the checkWorkspace() for an example.

@Dhruv-Maradiya Dhruv-Maradiya linked a pull request Jan 30, 2025 that will close this issue
2 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
good first issue A good starting issue for contributors (issues with this label will appear in /contribute) package:pubspec_parse type-enhancement A request for a change that isn't a bug
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants