# JD V2

## What should before and after context look like for nested lists?

- need context for producing minimal diffs
- so we can insert an element into the middle of a list
- patch must apply only once so we need to add enough context

A:

```json
[[1,2,3],[4,6],[7,8,9]]

```

B:

```json
[[1,2,3],[4,5,6],[7,8,9]]
```

D:

```diff
@ [1,1]
  4
+ 5
  6
```

- the `4` and `6` are compared for equality
- no context means "end of list" or "beginning of list"

A:

```json
[2,3]
```

B:

```json
[1,2,3]
```

D:

```diff
@ [0]
+ 1
  2
```

- if a patch doesn't have enough context to prevent double application, more context is added

A:

```json
[1,2,2,3]
```

B:

```json
[1,2,2,2,3]
```

D:

```diff
@ [2]
  1
+ 2
  2
  2
  3
```

- the `3` prevents double application

## What should metadata look like?

- metadata applying to entire hunk (not just path) is a separate line
- version (2)
- merge patch behavior

```diff
^ {"version":"2"}
@ ["foo"]
- "bar"
+ "baz"
```

```diff
^ {"version":2,"merge":true}
@ ["foo"]
- "bar"
+ "baz"
```

```diff
^ {"version":2}
^ {"merge":true}
@ ["foo"]
- "bar"
+ "baz"
```

```diff
^ {"version":2}
^ {"merge":true}
^ {"tolerance": {"path": ["foo","number"], e: 0.000001}}
@ ["foo"]
- "bar"
+ "baz"
```

- metadata lines are additive
- so you can say `^ {"version":"2"}` once at the top of the file
- and it will be inherited by all subsequent hunks
- this leaves things more open for extension in the future

## What about in-path metadata?

- no more metadata in a list (`[["multiset"],{}]`)
- still objects mean set
- object in list means multiset
- object with keys means object identity
- other use cases are now in the line-level `^` metadata object

Set:

```diff
@ ["foo",{"id":"bar"}]
```

Multiset:

```diff
@ ["foo",[{"id":"bar"}]]
```

## Set and Multiset paths

- sets a noted as `{}` or another object with keys
- example: `@ ["foo", {}]`
- example: `@ ["foo", {"bar":1}, "baz"]`
- multisets are noted as `[]` or an array with an object with keys
- example: `@ ["foo", []]`
- example: `@ ["foo", [{"bar":1}], "baz"]`

## How should YAML map to JSON?

### Sets

```yaml
--- !!set
? "foo"
? "bar"
```

```json
[
  "foo",
  "bar"
]
```

with path element:

```json
{}
```

### Map with object keys

```yaml
--- !!map
{ one: two }: { foo: bar }
{ three: four }: { baz: bam }
```

```json
[
  [{"one":"two"},{"foo":"bar"}],
  [{"three":"four"},{"baz":"bam"}]
]
```

with path element:

```json
[[]]
```

### Multiset

```yaml
--- !mset
? "foo"
? "foo"
? "bar"
```

```json
[
  "foo",
  "foo",
  "bar"
]
```

with path element:

```json
[{}]
```

## Other path elements

### Set with object key ids

```json
{"id":"foo"}
```

### Map with an object key

```json
[[{"one":"two"}]]
```

### Map with a boolean key

```json
[[true]]
```

### Map with a string key

```json
"one"
```

### Multiset with object key ids

```json
[{"id":"foo"}]
```

## What should this mapping do?

- As long as metadata is retained, must be lossless
- Non-string maps are converted into a list of pairs
- Sets, being the most common use case, should have a short path notation
- A simple set is `{}` in a path
- A set with objects identified by key is `{"foo":"bar"}`

### How do I specify metadata?

Objects:

```json
{"Set":["foo","bar"]}
```

Through sets:

```json
{"Set":["foo",{},"bar"]}
```

Through multisets:

```json
{"Set":["foo",[{}],"bar"]}
```

Through lists:

```json
{"Set":["foo",[],"bar"]}
```

Through set with keys:

```json
{"Set":["foo",["foo","bar"]]}
```

Do I really need to do the whole object things for metadata?
Why can't I just provide a path which **shows** the metadata?

Objects:

```json
["foo","bar",{}]
```

Through sets:

```json
["foo",{},"bar",{}]
```

Through multisets:

```json
["foo",[{}],"bar",{}]
```

Through lists:

```json
["foo",[],"bar",{}]
```

Through set with keys:

```json
["foo",["foo","bar"],{}]
```

What about sets that have non-string ID keys?
First of all, that's really weird.
I could just do this:

```json
[[[{"one":"two"}]]]
```

## Reference

Here is a complete list of path element examples:

- List: `0`
- Object: `"foo"`
- Set: `{}`
- Set key: `{"id":"foo"}`
- Multiset: `[{}]`
- Multiset key: `[{"id":"foo"}]`

And to support YAML with non-string keys:

- Object with non-string key: `[true]`
- Set key with non-string key: `[true,"foo"]` (even number of values)
- Multiset with non-string key: `[[true,"foo"]]`

Here is a complete list of metadata elements:

- List: `[]`
- Object: (a string)
- Object with non-string key: `[(a value)]`
- Set: `{}` (in middle means all keys)
- Multiset: `[{}]` (in middle means all keys)
- Set keys (string and non-string): `["foo"]`
- Multiset keys (string and non-string: `[["foo"]]`

String (`"foo"`) to non-string (`true`) mapping

- Object: `"foo"` `[true]` (one non-string element)
- Set key: `{"foo":"bar"}` `[true,"bar"]` (even number of elements)
- Multiset key: `[{"foo":"bar"}]` `[[true,"bar"]]` (even number of elements)


## Option Structures

```json
[
	{
		"at": [],
		"opt": [
			{
				"at": ["foo","bar"],
				"opt": ["SET"]
			},
			{
				"at": ["baz",{},"boom"],  # Implies SET at "baz", so why do I need opt at all? 
				"opt": ["SET"]
			}
		]
	}
]
```

Alternative:

```json
[
	["foo"],                         # Expect object with key "foo" with anything inside
	["bar","baz",{}]                 # Expect object, object, list as SET
    ["bar","bam",{"precision":0.1}]  # Expect object, object, number with precision
]
```

Can I combine structures so "bar" isn't repeated?

```json
[
	["foo"],
	["bar", [
		["baz",{}],                  # But [[]] already has a meaning
		["bam",{"precision":0.1}]    # How do I know this isn't a set key?
	]]
]
```

What if I go for the more explicit PathOption but only paths?

```json
{
	"at": [],
	"then": [
		{
			"at": ["foo","bar",{}],    # SET at "foo", "bar"
		},
		{
			"at": ["baz",{},"boom",{}] # SET at "baz", set of objects, "boom"
		}
	]
}
```

I like this.
