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

JSON Replacer Parity #33

Open
Offroaders123 opened this issue Aug 15, 2023 · 0 comments
Open

JSON Replacer Parity #33

Offroaders123 opened this issue Aug 15, 2023 · 0 comments
Assignees
Labels
enhancement New feature or request

Comments

@Offroaders123
Copy link
Owner

Was thinking about how NBTify is meant to be fairly symmetrical to the JSON namespace, and remembered that neither the SNBT nor binary NBT modules support the replacer callback parameter.

I think I initially skipped over this because I didn't want to worry about supporting it on top of the already complex NBT process, and I didn't want to messify the codebase just to include something initially. I knew I could come back to it again later if it deemed worthy down the line. I think it's something helpful to have in general, for the serialization processes, and it's already in the JSON namespace's API, so I'm going to look into it now.

I was going to just get it all added tonight, because I thought it would be simple and quick to add. But having looked back at the standard lib type definitions, there's more overloads for JSON.stringify() than I remembered. So It's gonna take a little extra to get setup, and I think I'll want to do some additional refactors to the general NBTify API before I try and add these features into the existing stack.

// Standard lib typings for the JSON namespace

interface JSON {
  parse(text: string, reviver?: (this: any, key: string, value: any) => any): any;
  stringify(value: any, replacer?: (this: any, key: string, value: any) => any, space?: string | number): string;
  stringify(value: any, replacer?: (number | string)[] | null, space?: string | number): string;
}

The JSON.stringify() keys selector overload is the one that made me rethink quickly adding this, because I want it to be structurally sound, rather than just patched in real-quick. Anything to do with the serialization steps are definitely important, and even more-so when modifying the user's incoming data. You don't want to unexpectedly mess with that stuff! A lot could go wrong there.

Right now, NBTify just supports the space option with the stringify() function through an options object, which I used instead of a bare-parameter because I wanted to anticipate adding more possible options down the road. That's come to pass though, and I think I'll want to follow the JSON namespace's API instead.

// NBTify's current SNBT API

export declare function parse<T extends RootTag = any>(data: string): T;

export interface StringifyOptions {
    space?: string | number;
}
export declare function stringify<T extends RootTag = any>(data: T | NBTData<T>, options?: StringifyOptions): string;
@Offroaders123 Offroaders123 added the enhancement New feature or request label Aug 15, 2023
@Offroaders123 Offroaders123 self-assigned this Aug 15, 2023
Offroaders123 added a commit to Offroaders123/Bob that referenced this issue Nov 24, 2024
Realizing that implementing custom primitives don't really make sense, when you can instead just implement your own custom replacer and hydrater. I'm curious how this can relate to NBTify too, as well as in regards to this project itself. Maybe I can build new formats that are recursive to the base primitives themselves, but implement them by way of building into the base primitives themselves, rather than needing to implement a whole new tag schema into the format too. So it would be like how zip files allow for new metadata to be added, and that extra space in the file format/'syntax' (in terms of TypeScript in relation with JS 👀) can instead be used to define your own types of formats. I really like this concept! It's like dependency injection, but for file formats! I guess it's like how sometimes Minecraft stores JSON inside of NBT string tags.

Offroaders123/NBTify#33

Lightwork is absolutely one of my favorite albums, ever. The whole concept behind it has unapologetically changed me as a person.
Offroaders123 added a commit that referenced this issue Nov 24, 2024
I still need to implement `this` calling.

```js
JSON.parse('{ "heya": ["nice", "2342"] }', (key, value) => { console.log(key, value); return Array.isArray(value) && value[0] === "nice" ? BigInt(value[1]) : value });
```

#33
Offroaders123 added a commit that referenced this issue Nov 24, 2024
Something isn't quite working here, and I don't know what it is exactly yet.

#33
Offroaders123 added a commit that referenced this issue Nov 24, 2024
#33

So this is awesome! For some reason adding a transform for Uint8Array objects wasn't working. Having a custom setup for `Set` objects appears to be working though.

This makes me think actually, this configuration would actually work awesome with things like `FlatWorldLayers` in the `level.dat` for example, because you would just add a transform in there that adds an extra call to `JSON.stringify()` and friends. So having plain JS trees makes even more sense in this case :D

The end of my song 'Scopes' sounds a lot like Clown Core come to think of it!

Also, The Land of the Dear feels like a reference back to a bunch of my older projects, which makes sense why it feels so near and dear to me (pun unintended). It has a little bit of foreshadowing to my sound later on too.
Offroaders123 added a commit to Offroaders123/Bob that referenced this issue Nov 24, 2024
This isn't quite working, but it's almost there!

Offroaders123/NBTify#33
Offroaders123 added a commit to Offroaders123/Bob that referenced this issue Nov 29, 2024
Heck yeah!!! JSON replacer-reviver now works completely in implementing a recursive object structure.

Offroaders123/NBTify#22
Offroaders123/NBTify#33
Offroaders123 added a commit that referenced this issue Nov 30, 2024
Checking that the order properties are logged is in the same order that JSON.parse() logs them. Stringifying should be BFS, while parsing should be DFS. It's the order that they are traversed as the file is read/written through.

In theory this means that you would be able to write a replacer/reviver pair and it would work both with JSON and NBT, if you did things in a certain way. This seems like a very neat thing that could make converting between the formats much more safe. It seems like a natural progression for adding custom primitives to either format, by way of essentially transpiling them in.

Come to think of it, this would actually work very well for converting to and from NBTify primitives to Prismarine-NBT objects as well, that might be a nice way to add that to NBTify itself without needing to implement custom functions or options for that outright.

#33
#22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

1 participant