From 7e3bfbb68629a4a2aa69073a30138ead2dcb7682 Mon Sep 17 00:00:00 2001
From: ko_oler <kooler89@gmail.com>
Date: Thu, 1 Feb 2024 19:46:39 +0300
Subject: [PATCH] =?UTF-8?q?-=20=D0=BF=D0=B5=D1=80=D0=B5=D0=B4=D0=B5=D0=BB?=
 =?UTF-8?q?=D0=B0=D0=BD=20marshal/unmarshal=20=D0=B4=D0=BB=D1=8F=20=D0=B8?=
 =?UTF-8?q?=D0=BD=D1=82=D0=B5=D1=80=D1=84=D0=B5=D0=B9=D1=81=D0=B0=20ID=20-?=
 =?UTF-8?q?=20=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=20=D1=82?=
 =?UTF-8?q?=D0=B5=D1=81=D1=82=20=D0=B8=20=D0=B8=D1=81=D0=BF=D1=80=D0=B0?=
 =?UTF-8?q?=D0=B2=D0=BB=D0=B5=D0=BD=D1=8B=20=D1=82=D0=B5=D1=81=D1=82=D1=8B?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 id/client.go       |  21 ----
 id/collection.go   |  22 ----
 id/environment.go  |  22 ----
 id/field.go        |  22 ----
 id/id.go           |  32 ++---
 id/id_test.go      | 306 ++++++++-------------------------------------
 id/item.go         |  21 ----
 id/json.go         | 105 +++++++++-------
 id/json_test.go    | 148 +++++++++++++---------
 id/organization.go |  20 ---
 id/revision.go     |  22 ----
 id/role.go         |  39 +++---
 id/schema.go       |  22 ----
 id/service.go      |  20 ---
 id/space.go        |  21 ----
 id/user.go         |  21 ----
 16 files changed, 240 insertions(+), 624 deletions(-)

diff --git a/id/client.go b/id/client.go
index 56d0e2b2..c3c9a403 100644
--- a/id/client.go
+++ b/id/client.go
@@ -1,9 +1,5 @@
 package id
 
-import (
-	jsoniter "github.com/json-iterator/go"
-)
-
 const (
 	Client        = "client"
 	ClientsPrefix = "clients"
@@ -58,20 +54,3 @@ func parseClientID(parts []string) (*ClientID, error) {
 	id.ClientID = parts[3]
 	return &id, nil
 }
-func (t *ClientID) UnmarshalJSON(b []byte) error {
-	var data string
-	if err := jsoniter.Unmarshal(b, &data); err != nil {
-		return err
-	}
-	knownID, err := Parse(data)
-	if err != nil {
-		return err
-	}
-	t.SpaceID = knownID.(*ClientID).SpaceID
-	t.ClientID = knownID.(*ClientID).ClientID
-	return nil
-}
-
-func (t *ClientID) MarshalJSON() ([]byte, error) {
-	return []byte(t.String()), nil
-}
diff --git a/id/collection.go b/id/collection.go
index 029735ba..075abc84 100644
--- a/id/collection.go
+++ b/id/collection.go
@@ -1,9 +1,5 @@
 package id
 
-import (
-	jsoniter "github.com/json-iterator/go"
-)
-
 const (
 	Collection        = "collection"
 	CollectionsPrefix = "cols"
@@ -57,21 +53,3 @@ func parseCollectionID(parts []string) (*CollectionID, error) {
 	id.EnvironmentID = *envID
 	return &id, nil
 }
-
-func (t *CollectionID) UnmarshalJSON(b []byte) error {
-	var data string
-	if err := jsoniter.Unmarshal(b, &data); err != nil {
-		return err
-	}
-	knownID, err := Parse(data)
-	if err != nil {
-		return err
-	}
-	t.EnvironmentID = knownID.(*CollectionID).EnvironmentID
-	t.CollectionID = knownID.(*CollectionID).CollectionID
-	return nil
-}
-
-func (t *CollectionID) MarshalJSON() ([]byte, error) {
-	return []byte(t.String()), nil
-}
diff --git a/id/environment.go b/id/environment.go
index b8b08e83..ec8643a3 100644
--- a/id/environment.go
+++ b/id/environment.go
@@ -1,9 +1,5 @@
 package id
 
-import (
-	jsoniter "github.com/json-iterator/go"
-)
-
 const (
 	Environment        = "environment"
 	EnvironmentsPrefix = "envs"
@@ -58,21 +54,3 @@ func parseEnvironmentID(parts []string) (*EnvironmentID, error) {
 	id.SpaceID = *spaceID
 	return &id, nil
 }
-
-func (t *EnvironmentID) UnmarshalJSON(b []byte) error {
-	var data string
-	if err := jsoniter.Unmarshal(b, &data); err != nil {
-		return err
-	}
-	knownID, err := Parse(data)
-	if err != nil {
-		return err
-	}
-	t.SpaceID = knownID.(*EnvironmentID).SpaceID
-	t.EnvironmentID = knownID.(*EnvironmentID).EnvironmentID
-	return nil
-}
-
-func (t *EnvironmentID) MarshalJSON() ([]byte, error) {
-	return []byte(t.String()), nil
-}
diff --git a/id/field.go b/id/field.go
index d1539a2c..b30eb591 100644
--- a/id/field.go
+++ b/id/field.go
@@ -1,9 +1,5 @@
 package id
 
-import (
-	jsoniter "github.com/json-iterator/go"
-)
-
 const (
 	Field        = "field"
 	FieldsPrefix = "fields"
@@ -58,21 +54,3 @@ func parseFieldID(parts []string) (*FieldID, error) {
 	id.FieldName = parts[9]
 	return &id, nil
 }
-
-func (t *FieldID) UnmarshalJSON(b []byte) error {
-	var data string
-	if err := jsoniter.Unmarshal(b, &data); err != nil {
-		return err
-	}
-	knownID, err := Parse(data)
-	if err != nil {
-		return err
-	}
-	t.ItemID = knownID.(*FieldID).ItemID
-	t.FieldName = knownID.(*FieldID).FieldName
-	return nil
-}
-
-func (t *FieldID) MarshalJSON() ([]byte, error) {
-	return []byte(t.String()), nil
-}
diff --git a/id/id.go b/id/id.go
index 88cad22a..a1931feb 100644
--- a/id/id.go
+++ b/id/id.go
@@ -12,7 +12,7 @@ var (
 	ErrInvalidID = errors.New("invalid id")
 )
 
-type ID interface {
+type Descriptor interface {
 	String() string
 	Type() string
 	ToMap() map[string]any
@@ -20,55 +20,59 @@ type ID interface {
 	Validate() error
 }
 
-func Parse(s string) (ID, error) {
+type ID struct {
+	Descriptor
+}
+
+func Parse(s string) (*ID, error) {
 	parts := Split(s)
 
 	if id, _ := parseServiceID(parts); id != nil {
-		return id, nil
+		return &ID{Descriptor: id}, nil
 	}
 
 	if id, _ := parseUserID(parts); id != nil {
-		return id, nil
+		return &ID{Descriptor: id}, nil
 	}
 
 	if id, _ := parseOrganizationID(parts); id != nil {
-		return id, nil
+		return &ID{Descriptor: id}, nil
 	}
 
 	if id, _ := parseSpaceID(parts); id != nil {
-		return id, nil
+		return &ID{Descriptor: id}, nil
 	}
 
 	if id, _ := parseEnvironmentID(parts); id != nil {
-		return id, nil
+		return &ID{Descriptor: id}, nil
 	}
 
 	if id, _ := parseClientID(parts); id != nil {
-		return id, nil
+		return &ID{Descriptor: id}, nil
 	}
 
 	if id, _ := parseRoleID(parts); id != nil {
-		return id, nil
+		return &ID{Descriptor: id}, nil
 	}
 
 	if id, _ := parseCollectionID(parts); id != nil {
-		return id, nil
+		return &ID{Descriptor: id}, nil
 	}
 
 	if id, _ := parseSchemaID(parts); id != nil {
-		return id, nil
+		return &ID{Descriptor: id}, nil
 	}
 
 	if id, _ := parseItemID(parts); id != nil {
-		return id, nil
+		return &ID{Descriptor: id}, nil
 	}
 
 	if id, _ := parseRevisionID(parts); id != nil {
-		return id, nil
+		return &ID{Descriptor: id}, nil
 	}
 
 	if id, _ := parseFieldID(parts); id != nil {
-		return id, nil
+		return &ID{Descriptor: id}, nil
 	}
 
 	return nil, ErrInvalidID
diff --git a/id/id_test.go b/id/id_test.go
index 181c7459..eb992a23 100644
--- a/id/id_test.go
+++ b/id/id_test.go
@@ -1,11 +1,8 @@
 package id
 
 import (
-	"encoding/json"
 	"testing"
 
-	jsoniter "github.com/json-iterator/go"
-	"github.com/stretchr/testify/assert"
 	"github.com/stretchr/testify/require"
 )
 
@@ -13,78 +10,78 @@ func Test_ParseID(t *testing.T) {
 	tests := []struct {
 		name   string
 		id     string
-		result ID
+		result *ID
 	}{
 		{
 			name:   Service,
 			id:     "/services/<service_id>",
-			result: &ServiceID{ServiceID: "<service_id>"},
+			result: &ID{Descriptor: &ServiceID{ServiceID: "<service_id>"}},
 		},
 		{
 			name:   User,
 			id:     "/users/<user_id>",
-			result: &UserID{UserID: "<user_id>"},
+			result: &ID{Descriptor: &UserID{UserID: "<user_id>"}},
 		},
 		{
 			name:   Organization,
 			id:     "/orgs/<org_id>",
-			result: &OrganizationID{OrganizationID: "<org_id>"},
+			result: &ID{Descriptor: &OrganizationID{OrganizationID: "<org_id>"}},
 		},
 		{
 			name:   Space,
 			id:     "/spaces/<space_id>",
-			result: &SpaceID{SpaceID: "<space_id>"},
+			result: &ID{Descriptor: &SpaceID{SpaceID: "<space_id>"}},
 		},
 		{
 			name: Client,
 			id:   "/spaces/<space_id>/clients/<client_id>",
-			result: &ClientID{
+			result: &ID{Descriptor: &ClientID{
 				SpaceID:  SpaceID{SpaceID: "<space_id>"},
 				ClientID: "<client_id>",
-			},
+			}},
 		},
 		{
 			name: Role,
 			id:   "/spaces/<space_id>/roles/<role_id>",
-			result: &RoleID{
+			result: &ID{Descriptor: &RoleID{
 				SpaceID: SpaceID{SpaceID: "<space_id>"},
 				RoleID:  "<role_id>",
-			},
+			}},
 		},
 		{
 			name: Environment,
 			id:   "/spaces/<space_id>/envs/<env_id>",
-			result: &EnvironmentID{
+			result: &ID{Descriptor: &EnvironmentID{
 				SpaceID:       SpaceID{SpaceID: "<space_id>"},
 				EnvironmentID: "<env_id>",
-			},
+			}},
 		},
 		{
 			name: Collection,
 			id:   "/spaces/<space_id>/envs/<env_id>/cols/<collection_id>",
-			result: &CollectionID{
+			result: &ID{Descriptor: &CollectionID{
 				EnvironmentID: EnvironmentID{
 					SpaceID:       SpaceID{SpaceID: "<space_id>"},
 					EnvironmentID: "<env_id>",
 				},
 				CollectionID: "<collection_id>",
-			},
+			}},
 		},
 		{
 			name: Schema,
 			id:   "/spaces/<space_id>/envs/<env_id>/schema/<collection_id>",
-			result: &SchemaID{
+			result: &ID{Descriptor: &SchemaID{
 				EnvironmentID: EnvironmentID{
 					SpaceID:       SpaceID{SpaceID: "<space_id>"},
 					EnvironmentID: "<env_id>",
 				},
 				SchemaID: "<collection_id>",
-			},
+			}},
 		},
 		{
 			name: Item,
 			id:   "/spaces/<space_id>/envs/<env_id>/cols/<collection_id>/items/<item_id>",
-			result: &ItemID{
+			result: &ID{Descriptor: &ItemID{
 				CollectionID: CollectionID{
 					EnvironmentID: EnvironmentID{
 						SpaceID:       SpaceID{SpaceID: "<space_id>"},
@@ -93,12 +90,12 @@ func Test_ParseID(t *testing.T) {
 					CollectionID: "<collection_id>",
 				},
 				ItemID: "<item_id>",
-			},
+			}},
 		},
 		{
 			name: Revision,
 			id:   "/spaces/<space_id>/envs/<env_id>/cols/<collection_id>/items/<item_id>/revs/<rev_id>",
-			result: &RevisionID{
+			result: &ID{Descriptor: &RevisionID{
 				ItemID: ItemID{
 					CollectionID: CollectionID{
 						EnvironmentID: EnvironmentID{
@@ -110,12 +107,12 @@ func Test_ParseID(t *testing.T) {
 					ItemID: "<item_id>",
 				},
 				RevisionID: "<rev_id>",
-			},
+			}},
 		},
 		{
 			name: Field,
 			id:   "/spaces/<space_id>/envs/<env_id>/cols/<collection_id>/items/<item_id>/fields/<field_name>",
-			result: &FieldID{
+			result: &ID{Descriptor: &FieldID{
 				ItemID: ItemID{
 					CollectionID: CollectionID{
 						EnvironmentID: EnvironmentID{
@@ -127,7 +124,7 @@ func Test_ParseID(t *testing.T) {
 					ItemID: "<item_id>",
 				},
 				FieldName: "<field_name>",
-			},
+			}},
 		},
 	}
 	for _, tt := range tests {
@@ -148,84 +145,84 @@ func Test_Map(t *testing.T) {
 	}{
 		{
 			name: Service,
-			id:   &ServiceID{},
+			id:   ID{Descriptor: &ServiceID{}},
 			from: map[string]any{"service_id": "<service_id>"},
-			to:   &ServiceID{ServiceID: "<service_id>"},
+			to:   ID{Descriptor: &ServiceID{ServiceID: "<service_id>"}},
 		},
 		{
 			name: User,
-			id:   &UserID{},
+			id:   ID{Descriptor: &UserID{}},
 			from: map[string]any{"user_id": "<user_id>"},
-			to:   &UserID{UserID: "<user_id>"},
+			to:   ID{Descriptor: &UserID{UserID: "<user_id>"}},
 		},
 		{
 			name: Organization,
-			id:   &OrganizationID{},
+			id:   ID{Descriptor: &OrganizationID{}},
 			from: map[string]any{"organization_id": "<org_id>"},
-			to:   &OrganizationID{OrganizationID: "<org_id>"},
+			to:   ID{Descriptor: &OrganizationID{OrganizationID: "<org_id>"}},
 		},
 		{
 			name: Space,
-			id:   &SpaceID{},
+			id:   ID{Descriptor: &SpaceID{}},
 			from: map[string]any{"space_id": "<space_id>"},
-			to:   &SpaceID{SpaceID: "<space_id>"},
+			to:   ID{Descriptor: &SpaceID{SpaceID: "<space_id>"}},
 		},
 		{
 			name: Client,
-			id:   &ClientID{},
+			id:   ID{Descriptor: &ClientID{}},
 			from: map[string]any{"space_id": "<space_id>", "client_id": "<client_id>"},
-			to: &ClientID{
+			to: ID{Descriptor: &ClientID{
 				SpaceID:  SpaceID{SpaceID: "<space_id>"},
 				ClientID: "<client_id>",
-			},
+			}},
 		},
 		{
 			name: Role,
-			id:   &RoleID{},
+			id:   ID{Descriptor: &RoleID{}},
 			from: map[string]any{"space_id": "<space_id>", "role_id": "<role_id>"},
-			to: &RoleID{
+			to: ID{Descriptor: &RoleID{
 				SpaceID: SpaceID{SpaceID: "<space_id>"},
 				RoleID:  "<role_id>",
-			},
+			}},
 		},
 		{
 			name: Environment,
-			id:   &EnvironmentID{},
+			id:   ID{Descriptor: &EnvironmentID{}},
 			from: map[string]any{"space_id": "<space_id>", "env_id": "<env_id>"},
-			to: &EnvironmentID{
+			to: ID{Descriptor: &EnvironmentID{
 				SpaceID:       SpaceID{SpaceID: "<space_id>"},
 				EnvironmentID: "<env_id>",
-			},
+			}},
 		},
 		{
 			name: Collection,
-			id:   &CollectionID{},
+			id:   ID{Descriptor: &CollectionID{}},
 			from: map[string]any{"space_id": "<space_id>", "env_id": "<env_id>", "col_id": "<collection_id>"},
-			to: &CollectionID{
+			to: ID{Descriptor: &CollectionID{
 				EnvironmentID: EnvironmentID{
 					SpaceID:       SpaceID{SpaceID: "<space_id>"},
 					EnvironmentID: "<env_id>",
 				},
 				CollectionID: "<collection_id>",
-			},
+			}},
 		},
 		{
 			name: Schema,
-			id:   &SchemaID{},
+			id:   ID{Descriptor: &SchemaID{}},
 			from: map[string]any{"space_id": "<space_id>", "env_id": "<env_id>", "schema_id": "<collection_id>"},
-			to: &SchemaID{
+			to: ID{Descriptor: &SchemaID{
 				EnvironmentID: EnvironmentID{
 					SpaceID:       SpaceID{SpaceID: "<space_id>"},
 					EnvironmentID: "<env_id>",
 				},
 				SchemaID: "<collection_id>",
-			},
+			}},
 		},
 		{
 			name: Item,
-			id:   &ItemID{},
+			id:   ID{Descriptor: &ItemID{}},
 			from: map[string]any{"space_id": "<space_id>", "env_id": "<env_id>", "col_id": "<collection_id>", "item_id": "<item_id>"},
-			to: &ItemID{
+			to: ID{Descriptor: &ItemID{
 				CollectionID: CollectionID{
 					EnvironmentID: EnvironmentID{
 						SpaceID:       SpaceID{SpaceID: "<space_id>"},
@@ -234,13 +231,13 @@ func Test_Map(t *testing.T) {
 					CollectionID: "<collection_id>",
 				},
 				ItemID: "<item_id>",
-			},
+			}},
 		},
 		{
 			name: Revision,
-			id:   &RevisionID{},
+			id:   ID{Descriptor: &RevisionID{}},
 			from: map[string]any{"space_id": "<space_id>", "env_id": "<env_id>", "col_id": "<collection_id>", "item_id": "<item_id>", "rev_id": "<rev_id>"},
-			to: &RevisionID{
+			to: ID{Descriptor: &RevisionID{
 				ItemID: ItemID{
 					CollectionID: CollectionID{
 						EnvironmentID: EnvironmentID{
@@ -252,13 +249,13 @@ func Test_Map(t *testing.T) {
 					ItemID: "<item_id>",
 				},
 				RevisionID: "<rev_id>",
-			},
+			}},
 		},
 		{
 			name: Field,
-			id:   &FieldID{},
+			id:   ID{Descriptor: &FieldID{}},
 			from: map[string]any{"space_id": "<space_id>", "env_id": "<env_id>", "col_id": "<collection_id>", "item_id": "<item_id>", "field_name": "<field_name>"},
-			to: &FieldID{
+			to: ID{Descriptor: &FieldID{
 				ItemID: ItemID{
 					CollectionID: CollectionID{
 						EnvironmentID: EnvironmentID{
@@ -271,7 +268,7 @@ func Test_Map(t *testing.T) {
 				},
 				FieldName: "<field_name>",
 			},
-		},
+			}},
 	}
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
@@ -282,200 +279,3 @@ func Test_Map(t *testing.T) {
 		})
 	}
 }
-
-func Test_MarshalJSON(t *testing.T) {
-	tests := []struct {
-		name string
-		json string
-		id   json.Marshaler
-	}{
-		{
-			Organization,
-			"/orgs/<org_id>",
-			&OrganizationID{OrganizationID: "<org_id>"},
-		},
-		{
-			Service,
-			"/services/<service_id>",
-			&ServiceID{ServiceID: "<service_id>"},
-		},
-		{
-			Space,
-			"/spaces/<space_id>",
-			&SpaceID{SpaceID: "<space_id>"},
-		},
-		{
-			Environment,
-			"/spaces/<space_id>/envs/<env_id>",
-			&EnvironmentID{SpaceID: SpaceID{SpaceID: "<space_id>"}, EnvironmentID: "<env_id>"},
-		},
-		{
-			Client,
-			"/spaces/<space_id>/clients/<client_id>",
-			&ClientID{SpaceID: SpaceID{SpaceID: "<space_id>"}, ClientID: "<client_id>"},
-		},
-		{
-			Role,
-			"/spaces/<space_id>/roles/<role_id>",
-			&RoleID{SpaceID: SpaceID{SpaceID: "<space_id>"}, RoleID: "<role_id>"},
-		},
-		{
-			Collection,
-			"/spaces/<space_id>/envs/<env_id>/cols/<coll_id>",
-			&CollectionID{EnvironmentID: EnvironmentID{SpaceID: SpaceID{SpaceID: "<space_id>"}, EnvironmentID: "<env_id>"}, CollectionID: "<coll_id>"},
-		},
-		{
-			Schema,
-			"/spaces/<space_id>/envs/<env_id>/schema/<coll_id>",
-			&SchemaID{EnvironmentID: EnvironmentID{SpaceID: SpaceID{SpaceID: "<space_id>"}, EnvironmentID: "<env_id>"}, SchemaID: "<coll_id>"},
-		},
-		{
-			Item,
-			"/spaces/<space_id>/envs/<env_id>/cols/<coll_id>/items/<item_id>",
-			&ItemID{CollectionID: CollectionID{EnvironmentID: EnvironmentID{SpaceID: SpaceID{SpaceID: "<space_id>"}, EnvironmentID: "<env_id>"}, CollectionID: "<coll_id>"}, ItemID: "<item_id>"},
-		},
-		{
-			Revision,
-			"/spaces/<space_id>/envs/<env_id>/cols/<coll_id>/items/<item_id>/revs/<rev_id>",
-			&RevisionID{ItemID: ItemID{CollectionID: CollectionID{EnvironmentID: EnvironmentID{SpaceID: SpaceID{SpaceID: "<space_id>"}, EnvironmentID: "<env_id>"}, CollectionID: "<coll_id>"}, ItemID: "<item_id>"}, RevisionID: "<rev_id>"},
-		},
-		{
-			Field,
-			"/spaces/<space_id>/envs/<env_id>/cols/<coll_id>/items/<item_id>/fields/<field_name>",
-			&FieldID{ItemID: ItemID{CollectionID: CollectionID{EnvironmentID: EnvironmentID{SpaceID: SpaceID{SpaceID: "<space_id>"}, EnvironmentID: "<env_id>"}, CollectionID: "<coll_id>"}, ItemID: "<item_id>"}, FieldName: "<field_name>"},
-		},
-	}
-	for _, tt := range tests {
-		t.Run(tt.name, func(t *testing.T) {
-			b, err := jsoniter.Marshal(tt.id)
-			require.NoError(t, err)
-			assert.Equal(t, tt.json, string(b))
-		})
-	}
-}
-
-func Test_UnmarshalJSON(t *testing.T) {
-	tests := []struct {
-		name string
-		json string
-		id   json.Unmarshaler
-	}{
-		{
-			Organization,
-			"\"/orgs/<org_id>\"",
-			&OrganizationID{OrganizationID: "<org_id>"},
-		},
-		{
-			Service,
-			"\"/services/<service_id>\"",
-			&ServiceID{ServiceID: "<service_id>"},
-		},
-		{
-			Space,
-			"\"/spaces/<space_id>\"",
-			&SpaceID{SpaceID: "<space_id>"},
-		},
-		{
-			Environment,
-			"\"/spaces/<space_id>/envs/<env_id>\"",
-			&EnvironmentID{SpaceID: SpaceID{SpaceID: "<space_id>"}, EnvironmentID: "<env_id>"},
-		},
-		{
-			Client,
-			"\"/spaces/<space_id>/clients/<client_id>\"",
-			&ClientID{SpaceID: SpaceID{SpaceID: "<space_id>"}, ClientID: "<client_id>"},
-		},
-		{
-			Role,
-			"\"/spaces/<space_id>/roles/<role_id>\"",
-			&RoleID{SpaceID: SpaceID{SpaceID: "<space_id>"}, RoleID: "<role_id>"},
-		},
-		{
-			Collection,
-			"\"/spaces/<space_id>/envs/<env_id>/cols/<coll_id>\"",
-			&CollectionID{EnvironmentID: EnvironmentID{SpaceID: SpaceID{SpaceID: "<space_id>"}, EnvironmentID: "<env_id>"}, CollectionID: "<coll_id>"},
-		},
-		{
-			Schema,
-			"\"/spaces/<space_id>/envs/<env_id>/schema/<coll_id>\"",
-			&SchemaID{EnvironmentID: EnvironmentID{SpaceID: SpaceID{SpaceID: "<space_id>"}, EnvironmentID: "<env_id>"}, SchemaID: "<coll_id>"},
-		},
-		{
-			Item,
-			"\"/spaces/<space_id>/envs/<env_id>/cols/<coll_id>/items/<item_id>\"",
-			&ItemID{CollectionID: CollectionID{EnvironmentID: EnvironmentID{SpaceID: SpaceID{SpaceID: "<space_id>"}, EnvironmentID: "<env_id>"}, CollectionID: "<coll_id>"}, ItemID: "<item_id>"},
-		},
-		{
-			Revision,
-			"\"/spaces/<space_id>/envs/<env_id>/cols/<coll_id>/items/<item_id>/revs/<rev_id>\"",
-			&RevisionID{ItemID: ItemID{CollectionID: CollectionID{EnvironmentID: EnvironmentID{SpaceID: SpaceID{SpaceID: "<space_id>"}, EnvironmentID: "<env_id>"}, CollectionID: "<coll_id>"}, ItemID: "<item_id>"}, RevisionID: "<rev_id>"},
-		},
-		{
-			Field,
-			"\"/spaces/<space_id>/envs/<env_id>/cols/<coll_id>/items/<item_id>/fields/<field_name>\"",
-			&FieldID{ItemID: ItemID{CollectionID: CollectionID{EnvironmentID: EnvironmentID{SpaceID: SpaceID{SpaceID: "<space_id>"}, EnvironmentID: "<env_id>"}, CollectionID: "<coll_id>"}, ItemID: "<item_id>"}, FieldName: "<field_name>"},
-		},
-	}
-
-	for _, tt := range tests {
-		t.Run(tt.name, func(t *testing.T) {
-			switch tt.name {
-			case Organization:
-				v := new(OrganizationID)
-				err := v.UnmarshalJSON([]byte(tt.json))
-				require.NoError(t, err)
-				assert.Equal(t, tt.id, v)
-			case Service:
-				v := new(ServiceID)
-				err := v.UnmarshalJSON([]byte(tt.json))
-				require.NoError(t, err)
-				assert.Equal(t, tt.id, v)
-			case Space:
-				v := new(SpaceID)
-				err := v.UnmarshalJSON([]byte(tt.json))
-				require.NoError(t, err)
-				assert.Equal(t, tt.id, v)
-			case Environment:
-				v := new(EnvironmentID)
-				err := v.UnmarshalJSON([]byte(tt.json))
-				require.NoError(t, err)
-				assert.Equal(t, tt.id, v)
-			case Client:
-				v := new(ClientID)
-				err := v.UnmarshalJSON([]byte(tt.json))
-				require.NoError(t, err)
-				assert.Equal(t, tt.id, v)
-			case Role:
-				v := new(RoleID)
-				err := v.UnmarshalJSON([]byte(tt.json))
-				require.NoError(t, err)
-				assert.Equal(t, tt.id, v)
-			case Collection:
-				v := new(CollectionID)
-				err := v.UnmarshalJSON([]byte(tt.json))
-				require.NoError(t, err)
-				assert.Equal(t, tt.id, v)
-			case Schema:
-				v := new(SchemaID)
-				err := v.UnmarshalJSON([]byte(tt.json))
-				require.NoError(t, err)
-				assert.Equal(t, tt.id, v)
-			case Item:
-				v := new(ItemID)
-				err := v.UnmarshalJSON([]byte(tt.json))
-				require.NoError(t, err)
-				assert.Equal(t, tt.id, v)
-			case Revision:
-				v := new(RevisionID)
-				err := v.UnmarshalJSON([]byte(tt.json))
-				require.NoError(t, err)
-				assert.Equal(t, tt.id, v)
-			case Field:
-				v := new(FieldID)
-				err := v.UnmarshalJSON([]byte(tt.json))
-				require.NoError(t, err)
-				assert.Equal(t, tt.id, v)
-			}
-		})
-	}
-}
diff --git a/id/item.go b/id/item.go
index 224c3e19..1668dd16 100644
--- a/id/item.go
+++ b/id/item.go
@@ -1,9 +1,5 @@
 package id
 
-import (
-	jsoniter "github.com/json-iterator/go"
-)
-
 const (
 	Item        = "item"
 	ItemsPrefix = "items"
@@ -58,20 +54,3 @@ func parseItemID(parts []string) (*ItemID, error) {
 	id.ItemID = parts[7]
 	return &id, nil
 }
-func (t *ItemID) UnmarshalJSON(b []byte) error {
-	var data string
-	if err := jsoniter.Unmarshal(b, &data); err != nil {
-		return err
-	}
-	knownID, err := Parse(data)
-	if err != nil {
-		return err
-	}
-	t.CollectionID = knownID.(*ItemID).CollectionID
-	t.ItemID = knownID.(*ItemID).ItemID
-	return nil
-}
-
-func (t *ItemID) MarshalJSON() ([]byte, error) {
-	return []byte(t.String()), nil
-}
diff --git a/id/json.go b/id/json.go
index 9c468ceb..0a0a5789 100644
--- a/id/json.go
+++ b/id/json.go
@@ -1,59 +1,72 @@
 package id
 
 import (
-	"encoding/json"
-	"reflect"
-
 	jsoniter "github.com/json-iterator/go"
 )
 
-var knownImplementations = []ID{
-	&SpaceID{},
-	&EnvironmentID{},
-	&CollectionID{},
-	&ClientID{},
-	&RoleID{},
-	&SchemaID{},
-	&ItemID{},
-	&RevisionID{},
-	&FieldID{},
-	&OrganizationID{},
-	&ServiceID{},
-	&UserID{},
-}
-
-type JSONID struct {
-	Value ID `json:"value"`
+func (id *ID) MarshalJSON() ([]byte, error) {
+	return jsoniter.Marshal(id.String())
 }
 
-func (t *JSONID) UnmarshalJSON(b []byte) error {
-	var data struct {
-		Type  string
-		Value json.RawMessage
-	}
-	if err := jsoniter.Unmarshal(b, &data); err != nil {
+func (id *ID) UnmarshalJSON(b []byte) error {
+	var s string
+	var err error
+	if err = jsoniter.Unmarshal(b, &s); err != nil {
 		return err
 	}
-	for _, knownImplementation := range knownImplementations {
-		if knownImplementation.Type() == data.Type {
-			knownType := reflect.TypeOf(knownImplementation)
-			target := reflect.New(knownType)
-			if err := jsoniter.Unmarshal(data.Value, target.Interface()); err != nil {
-				return err
-			}
-			t.Value = target.Elem().Interface().(ID)
-			return nil
-		}
+	id.Descriptor, err = Parse(s)
+	switch id.Type() {
+	case Space:
+		m := id.ToMap()
+		id.Descriptor = new(SpaceID)
+		_ = id.FromMap(m)
+	case Environment:
+		m := id.ToMap()
+		id.Descriptor = new(EnvironmentID)
+		_ = id.FromMap(m)
+	case Collection:
+		m := id.ToMap()
+		id.Descriptor = new(CollectionID)
+		_ = id.FromMap(m)
+	case Schema:
+		m := id.ToMap()
+		id.Descriptor = new(SchemaID)
+		_ = id.FromMap(m)
+	case Item:
+		m := id.ToMap()
+		id.Descriptor = new(ItemID)
+		_ = id.FromMap(m)
+	case Revision:
+		m := id.ToMap()
+		id.Descriptor = new(RevisionID)
+		_ = id.FromMap(m)
+	case Field:
+		m := id.ToMap()
+		id.Descriptor = new(FieldID)
+		_ = id.FromMap(m)
+	case Client:
+		m := id.ToMap()
+		id.Descriptor = new(ClientID)
+		_ = id.FromMap(m)
+	case Role:
+		m := id.ToMap()
+		id.Descriptor = new(RoleID)
+		_ = id.FromMap(m)
+	case User:
+		m := id.ToMap()
+		id.Descriptor = new(UserID)
+		_ = id.FromMap(m)
+	case Organization:
+		m := id.ToMap()
+		id.Descriptor = new(OrganizationID)
+		_ = id.FromMap(m)
+	case Service:
+		m := id.ToMap()
+		id.Descriptor = new(ServiceID)
+		_ = id.FromMap(m)
+	}
+	if err != nil {
+		return err
 	}
 	return nil
 }
-
-func (t *JSONID) MarshalJSON() ([]byte, error) {
-	return json.Marshal(struct {
-		Type  string
-		Value any
-	}{
-		Type:  reflect.TypeOf(t.Value).String(),
-		Value: t.Value,
-	})
-}
diff --git a/id/json_test.go b/id/json_test.go
index 7974a13d..b81650cf 100644
--- a/id/json_test.go
+++ b/id/json_test.go
@@ -8,7 +8,7 @@ import (
 	"github.com/stretchr/testify/require"
 )
 
-func TestJSONID_MarshalJSON(t *testing.T) {
+func TestID_MarshalJSON(t *testing.T) {
 	tests := []struct {
 		name  string
 		Value ID
@@ -16,77 +16,75 @@ func TestJSONID_MarshalJSON(t *testing.T) {
 	}{
 		{
 			name:  Organization,
-			Value: &OrganizationID{OrganizationID: "1"},
-			want:  "/orgs/1",
+			Value: ID{Descriptor: &OrganizationID{OrganizationID: "1"}},
+			want:  `"/orgs/1"`,
 		},
 		{
 			name:  User,
-			Value: &UserID{UserID: "1"},
-			want:  "/users/1",
+			Value: ID{Descriptor: &UserID{UserID: "1"}},
+			want:  `"/users/1"`,
 		},
 		{
 			name:  Service,
-			Value: &ServiceID{ServiceID: "1"},
-			want:  "/services/1",
+			Value: ID{Descriptor: &ServiceID{ServiceID: "1"}},
+			want:  `"/services/1"`,
 		},
 		{
 			name:  Space,
-			Value: &SpaceID{SpaceID: "1"},
-			want:  "/spaces/1",
+			Value: ID{Descriptor: &SpaceID{SpaceID: "1"}},
+			want:  `"/spaces/1"`,
 		},
 		{
 			name:  Environment,
-			Value: &EnvironmentID{EnvironmentID: "1", SpaceID: SpaceID{SpaceID: "1"}},
-			want:  "/spaces/1/envs/1",
+			Value: ID{Descriptor: &EnvironmentID{EnvironmentID: "1", SpaceID: SpaceID{SpaceID: "1"}}},
+			want:  `"/spaces/1/envs/1"`,
 		},
 		{
 			name:  Client,
-			Value: &ClientID{ClientID: "1", SpaceID: SpaceID{SpaceID: "1"}},
-			want:  "/spaces/1/clients/1",
+			Value: ID{Descriptor: &ClientID{ClientID: "1", SpaceID: SpaceID{SpaceID: "1"}}},
+			want:  `"/spaces/1/clients/1"`,
 		},
 		{
 			name:  Role,
-			Value: &RoleID{RoleID: "1", SpaceID: SpaceID{SpaceID: "1"}},
-			want:  "/spaces/1/roles/1",
+			Value: ID{Descriptor: &RoleID{RoleID: "1", SpaceID: SpaceID{SpaceID: "1"}}},
+			want:  `"/spaces/1/roles/1"`,
 		},
 		{
 			name:  Collection,
-			Value: &CollectionID{CollectionID: "1", EnvironmentID: EnvironmentID{EnvironmentID: "1", SpaceID: SpaceID{SpaceID: "1"}}},
-			want:  "/spaces/1/envs/1/cols/1",
+			Value: ID{Descriptor: &CollectionID{CollectionID: "1", EnvironmentID: EnvironmentID{EnvironmentID: "1", SpaceID: SpaceID{SpaceID: "1"}}}},
+			want:  `"/spaces/1/envs/1/cols/1"`,
 		},
 		{
 			name:  Schema,
-			Value: &SchemaID{SchemaID: "1", EnvironmentID: EnvironmentID{EnvironmentID: "1", SpaceID: SpaceID{SpaceID: "1"}}},
-			want:  "/spaces/1/envs/1/schema/1",
+			Value: ID{Descriptor: &SchemaID{SchemaID: "1", EnvironmentID: EnvironmentID{EnvironmentID: "1", SpaceID: SpaceID{SpaceID: "1"}}}},
+			want:  `"/spaces/1/envs/1/schema/1"`,
 		},
 		{
 			name:  Item,
-			Value: &ItemID{ItemID: "1", CollectionID: CollectionID{CollectionID: "1", EnvironmentID: EnvironmentID{EnvironmentID: "1", SpaceID: SpaceID{SpaceID: "1"}}}},
-			want:  "/spaces/1/envs/1/cols/1/items/1",
+			Value: ID{Descriptor: &ItemID{ItemID: "1", CollectionID: CollectionID{CollectionID: "1", EnvironmentID: EnvironmentID{EnvironmentID: "1", SpaceID: SpaceID{SpaceID: "1"}}}}},
+			want:  `"/spaces/1/envs/1/cols/1/items/1"`,
 		},
 		{
 			name:  Revision,
-			Value: &RevisionID{RevisionID: "1", ItemID: ItemID{ItemID: "1", CollectionID: CollectionID{CollectionID: "1", EnvironmentID: EnvironmentID{EnvironmentID: "1", SpaceID: SpaceID{SpaceID: "1"}}}}},
-			want:  "/spaces/1/envs/1/cols/1/items/1/revs/1",
+			Value: ID{Descriptor: &RevisionID{RevisionID: "1", ItemID: ItemID{ItemID: "1", CollectionID: CollectionID{CollectionID: "1", EnvironmentID: EnvironmentID{EnvironmentID: "1", SpaceID: SpaceID{SpaceID: "1"}}}}}},
+			want:  `"/spaces/1/envs/1/cols/1/items/1/revs/1"`,
 		},
 		{
 			name:  Field,
-			Value: &FieldID{FieldName: "1", ItemID: ItemID{ItemID: "1", CollectionID: CollectionID{CollectionID: "1", EnvironmentID: EnvironmentID{EnvironmentID: "1", SpaceID: SpaceID{SpaceID: "1"}}}}},
-			want:  "/spaces/1/envs/1/cols/1/items/1/fields/1",
+			Value: ID{Descriptor: &FieldID{FieldName: "1", ItemID: ItemID{ItemID: "1", CollectionID: CollectionID{CollectionID: "1", EnvironmentID: EnvironmentID{EnvironmentID: "1", SpaceID: SpaceID{SpaceID: "1"}}}}}},
+			want:  `"/spaces/1/envs/1/cols/1/items/1/fields/1"`,
 		},
 	}
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
-			var j JSONID
-			j.Value = tt.Value
 			got, err := jsoniter.Marshal(&tt.Value)
 			require.NoError(t, err)
-			assert.Equalf(t, tt.want, string(got), "MarshalJSON()")
+			assert.Equal(t, tt.want, string(got))
 		})
 	}
 }
 
-func TestJSONID_UnmarshalJSON(t *testing.T) {
+func TestID_UnmarshalJSON(t *testing.T) {
 	tests := []struct {
 		name  string
 		Value ID
@@ -94,70 +92,108 @@ func TestJSONID_UnmarshalJSON(t *testing.T) {
 	}{
 		{
 			name:  Organization,
-			Value: &OrganizationID{OrganizationID: "1"},
-			b:     []byte(`{"type": "organization", "value": "/orgs/1"}`),
+			Value: ID{Descriptor: &OrganizationID{OrganizationID: "1"}},
+			b:     []byte(`"/orgs/1"`),
 		},
 		{
 			name:  User,
-			Value: &UserID{UserID: "1"},
-			b:     []byte(`{"type": "user", "value": "/users/1"}`),
+			Value: ID{Descriptor: &UserID{UserID: "1"}},
+			b:     []byte(`"/users/1"`),
 		},
 		{
 			name:  Service,
-			Value: &ServiceID{ServiceID: "1"},
-			b:     []byte(`{"type": "service", "value": "/services/1"}`),
+			Value: ID{Descriptor: &ServiceID{ServiceID: "1"}},
+			b:     []byte(`"/services/1"`),
 		},
 		{
 			name:  Space,
-			Value: &SpaceID{SpaceID: "1"},
-			b:     []byte(`{"type": "space", "value": "/spaces/1"}`),
+			Value: ID{Descriptor: &SpaceID{SpaceID: "1"}},
+			b:     []byte(`"/spaces/1"`),
 		},
 		{
 			name:  Environment,
-			Value: &EnvironmentID{EnvironmentID: "1", SpaceID: SpaceID{SpaceID: "1"}},
-			b:     []byte(`{"type": "environment", "value": "/spaces/1/envs/1"}`),
+			Value: ID{Descriptor: &EnvironmentID{EnvironmentID: "1", SpaceID: SpaceID{SpaceID: "1"}}},
+			b:     []byte(`"/spaces/1/envs/1"`),
 		},
 		{
 			name:  Client,
-			Value: &ClientID{ClientID: "1", SpaceID: SpaceID{SpaceID: "1"}},
-			b:     []byte(`{"type": "client", "value": "/spaces/1/clients/1"}`),
+			Value: ID{Descriptor: &ClientID{ClientID: "1", SpaceID: SpaceID{SpaceID: "1"}}},
+			b:     []byte(`"/spaces/1/clients/1"`),
 		},
 		{
 			name:  Role,
-			Value: &RoleID{RoleID: "1", SpaceID: SpaceID{SpaceID: "1"}},
-			b:     []byte(`{"type": "role", "value": "/spaces/1/roles/1"}`),
+			Value: ID{Descriptor: &RoleID{RoleID: "1", SpaceID: SpaceID{SpaceID: "1"}}},
+			b:     []byte(`"/spaces/1/roles/1"`),
 		},
 		{
 			name:  Collection,
-			Value: &CollectionID{CollectionID: "1", EnvironmentID: EnvironmentID{EnvironmentID: "1", SpaceID: SpaceID{SpaceID: "1"}}},
-			b:     []byte(`{"type": "collection", "value": "/spaces/1/envs/1/cols/1"}`),
+			Value: ID{Descriptor: &CollectionID{CollectionID: "1", EnvironmentID: EnvironmentID{EnvironmentID: "1", SpaceID: SpaceID{SpaceID: "1"}}}},
+			b:     []byte(`"/spaces/1/envs/1/cols/1"`),
 		},
 		{
 			name:  Schema,
-			Value: &SchemaID{SchemaID: "1", EnvironmentID: EnvironmentID{EnvironmentID: "1", SpaceID: SpaceID{SpaceID: "1"}}},
-			b:     []byte(`{"type": "schema", "value": "/spaces/1/envs/1/schema/1"}`),
+			Value: ID{Descriptor: &SchemaID{SchemaID: "1", EnvironmentID: EnvironmentID{EnvironmentID: "1", SpaceID: SpaceID{SpaceID: "1"}}}},
+			b:     []byte(`"/spaces/1/envs/1/schema/1"`),
 		},
 		{
 			name:  Item,
-			Value: &ItemID{ItemID: "1", CollectionID: CollectionID{CollectionID: "1", EnvironmentID: EnvironmentID{EnvironmentID: "1", SpaceID: SpaceID{SpaceID: "1"}}}},
-			b:     []byte(`{"type": "item", "value": "/spaces/1/envs/1/cols/1/items/1"}`),
+			Value: ID{Descriptor: &ItemID{ItemID: "1", CollectionID: CollectionID{CollectionID: "1", EnvironmentID: EnvironmentID{EnvironmentID: "1", SpaceID: SpaceID{SpaceID: "1"}}}}},
+			b:     []byte(`"/spaces/1/envs/1/cols/1/items/1"`),
 		},
 		{
 			name:  Revision,
-			Value: &RevisionID{RevisionID: "1", ItemID: ItemID{ItemID: "1", CollectionID: CollectionID{CollectionID: "1", EnvironmentID: EnvironmentID{EnvironmentID: "1", SpaceID: SpaceID{SpaceID: "1"}}}}},
-			b:     []byte(`{"type": "revision", "value": "/spaces/1/envs/1/cols/1/items/1/revs/1"}`),
+			Value: ID{Descriptor: &RevisionID{RevisionID: "1", ItemID: ItemID{ItemID: "1", CollectionID: CollectionID{CollectionID: "1", EnvironmentID: EnvironmentID{EnvironmentID: "1", SpaceID: SpaceID{SpaceID: "1"}}}}}},
+			b:     []byte(`"/spaces/1/envs/1/cols/1/items/1/revs/1"`),
 		},
 		{
 			name:  Field,
-			Value: &FieldID{FieldName: "1", ItemID: ItemID{ItemID: "1", CollectionID: CollectionID{CollectionID: "1", EnvironmentID: EnvironmentID{EnvironmentID: "1", SpaceID: SpaceID{SpaceID: "1"}}}}},
-			b:     []byte(`{"type": "field", "value": "/spaces/1/envs/1/cols/1/items/1/fields/1"}`),
+			Value: ID{Descriptor: &FieldID{FieldName: "1", ItemID: ItemID{ItemID: "1", CollectionID: CollectionID{CollectionID: "1", EnvironmentID: EnvironmentID{EnvironmentID: "1", SpaceID: SpaceID{SpaceID: "1"}}}}}},
+			b:     []byte(`"/spaces/1/envs/1/cols/1/items/1/fields/1"`),
 		},
 	}
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
-			var j JSONID
-			require.NoError(t, j.UnmarshalJSON(tt.b))
-			assert.Equal(t, j.Value, tt.Value)
+			var i ID
+			require.NoError(t, i.UnmarshalJSON(tt.b))
+			assert.Equal(t, i, tt.Value)
 		})
 	}
 }
+
+func TestID_JSON(t *testing.T) {
+	type data struct {
+		ID     *ID
+		Text   string
+		Number int
+	}
+
+	test1 := &data{
+		ID:     &ID{Descriptor: &SpaceID{SpaceID: Space}},
+		Text:   "text",
+		Number: 1,
+	}
+
+	b, err := jsoniter.Marshal(test1)
+	require.NoError(t, err)
+	assert.Equal(t, string(b), "{\"ID\":\"/spaces/space\",\"Text\":\"text\",\"Number\":1}", "проверяем корректность Marshal данных")
+
+	test2 := new(data)
+	err = jsoniter.Unmarshal(b, &test2)
+	require.NoError(t, err)
+	assert.Equal(t, test1, test2, "после Unmarshal объект должен совпадать с исходным")
+
+	test1 = &data{
+		ID:     &ID{Descriptor: &OrganizationID{OrganizationID: Organization}},
+		Text:   "text2",
+		Number: 2,
+	}
+
+	b, err = jsoniter.Marshal(test1)
+	require.NoError(t, err)
+	assert.Equal(t, string(b), "{\"ID\":\"/orgs/organization\",\"Text\":\"text2\",\"Number\":2}", "проверяем корректность Marshal данных")
+
+	test2 = new(data)
+	err = jsoniter.Unmarshal(b, &test2)
+	require.NoError(t, err)
+	assert.Equal(t, test1, test2, "после Unmarshal объект должен совпадать с исходным")
+}
diff --git a/id/organization.go b/id/organization.go
index 2c884140..7f2ca659 100644
--- a/id/organization.go
+++ b/id/organization.go
@@ -1,9 +1,5 @@
 package id
 
-import (
-	jsoniter "github.com/json-iterator/go"
-)
-
 const (
 	Organization        = "organization"
 	OrganizationsPrefix = "orgs"
@@ -46,19 +42,3 @@ func parseOrganizationID(parts []string) (*OrganizationID, error) {
 	id.OrganizationID = parts[1]
 	return &id, nil
 }
-func (t *OrganizationID) UnmarshalJSON(b []byte) error {
-	var data string
-	if err := jsoniter.Unmarshal(b, &data); err != nil {
-		return err
-	}
-	knownID, err := Parse(data)
-	if err != nil {
-		return err
-	}
-	t.OrganizationID = knownID.(*OrganizationID).OrganizationID
-	return nil
-}
-
-func (t *OrganizationID) MarshalJSON() ([]byte, error) {
-	return []byte(t.String()), nil
-}
diff --git a/id/revision.go b/id/revision.go
index a5a1caf1..3a111dfe 100644
--- a/id/revision.go
+++ b/id/revision.go
@@ -1,9 +1,5 @@
 package id
 
-import (
-	jsoniter "github.com/json-iterator/go"
-)
-
 const (
 	Revision        = "revision"
 	RevisionsPrefix = "revs"
@@ -58,21 +54,3 @@ func parseRevisionID(parts []string) (*RevisionID, error) {
 	id.RevisionID = parts[9]
 	return &id, nil
 }
-
-func (t *RevisionID) UnmarshalJSON(b []byte) error {
-	var data string
-	if err := jsoniter.Unmarshal(b, &data); err != nil {
-		return err
-	}
-	knownID, err := Parse(data)
-	if err != nil {
-		return err
-	}
-	t.ItemID = knownID.(*RevisionID).ItemID
-	t.RevisionID = knownID.(*RevisionID).RevisionID
-	return nil
-}
-
-func (t *RevisionID) MarshalJSON() ([]byte, error) {
-	return []byte(t.String()), nil
-}
diff --git a/id/role.go b/id/role.go
index 9dbfcd95..7080b23e 100644
--- a/id/role.go
+++ b/id/role.go
@@ -1,9 +1,5 @@
 package id
 
-import (
-	jsoniter "github.com/json-iterator/go"
-)
-
 const (
 	Role        = "role"
 	RolesPrefix = "roles"
@@ -59,20 +55,21 @@ func parseRoleID(parts []string) (*RoleID, error) {
 	return &id, nil
 }
 
-func (t *RoleID) UnmarshalJSON(b []byte) error {
-	var data string
-	if err := jsoniter.Unmarshal(b, &data); err != nil {
-		return err
-	}
-	knownID, err := Parse(data)
-	if err != nil {
-		return err
-	}
-	t.SpaceID = knownID.(*RoleID).SpaceID
-	t.RoleID = knownID.(*RoleID).RoleID
-	return nil
-}
-
-func (t *RoleID) MarshalJSON() ([]byte, error) {
-	return []byte(t.String()), nil
-}
+//
+//func (t *RoleID) UnmarshalJSON(b []byte) error {
+//	var data string
+//	if err := jsoniter.Unmarshal(b, &data); err != nil {
+//		return err
+//	}
+//	knownID, err := Parse(data)
+//	if err != nil {
+//		return err
+//	}
+//	t.SpaceID = knownID.(*RoleID).SpaceID
+//	t.RoleID = knownID.(*RoleID).RoleID
+//	return nil
+//}
+//
+//func (t *RoleID) MarshalJSON() ([]byte, error) {
+//	return []byte(t.String()), nil
+//}
diff --git a/id/schema.go b/id/schema.go
index 43c97a4f..213baa1d 100644
--- a/id/schema.go
+++ b/id/schema.go
@@ -1,9 +1,5 @@
 package id
 
-import (
-	jsoniter "github.com/json-iterator/go"
-)
-
 const (
 	Schema       = "schema"
 	SchemaPrefix = "schema"
@@ -58,21 +54,3 @@ func parseSchemaID(parts []string) (*SchemaID, error) {
 	id.SchemaID = parts[5]
 	return &id, nil
 }
-
-func (t *SchemaID) UnmarshalJSON(b []byte) error {
-	var data string
-	if err := jsoniter.Unmarshal(b, &data); err != nil {
-		return err
-	}
-	knownID, err := Parse(data)
-	if err != nil {
-		return err
-	}
-	t.EnvironmentID = knownID.(*SchemaID).EnvironmentID
-	t.SchemaID = knownID.(*SchemaID).SchemaID
-	return nil
-}
-
-func (t *SchemaID) MarshalJSON() ([]byte, error) {
-	return []byte(t.String()), nil
-}
diff --git a/id/service.go b/id/service.go
index 9a55357b..6c3a4400 100644
--- a/id/service.go
+++ b/id/service.go
@@ -1,9 +1,5 @@
 package id
 
-import (
-	jsoniter "github.com/json-iterator/go"
-)
-
 const (
 	Service        = "service"
 	ServicesPrefix = "services"
@@ -46,19 +42,3 @@ func parseServiceID(parts []string) (*ServiceID, error) {
 	id.ServiceID = parts[1]
 	return &id, nil
 }
-func (t *ServiceID) UnmarshalJSON(b []byte) error {
-	var data string
-	if err := jsoniter.Unmarshal(b, &data); err != nil {
-		return err
-	}
-	knownID, err := Parse(data)
-	if err != nil {
-		return err
-	}
-	t.ServiceID = knownID.(*ServiceID).ServiceID
-	return nil
-}
-
-func (t *ServiceID) MarshalJSON() ([]byte, error) {
-	return []byte(t.String()), nil
-}
diff --git a/id/space.go b/id/space.go
index 401fd58d..3d9d6c35 100644
--- a/id/space.go
+++ b/id/space.go
@@ -1,9 +1,5 @@
 package id
 
-import (
-	jsoniter "github.com/json-iterator/go"
-)
-
 const (
 	Space        = "space"
 	SpacesPrefix = "spaces"
@@ -46,20 +42,3 @@ func parseSpaceID(parts []string) (*SpaceID, error) {
 	id.SpaceID = parts[1]
 	return &id, nil
 }
-
-func (t *SpaceID) UnmarshalJSON(b []byte) error {
-	var data string
-	if err := jsoniter.Unmarshal(b, &data); err != nil {
-		return err
-	}
-	knownID, err := Parse(data)
-	if err != nil {
-		return err
-	}
-	t.SpaceID = knownID.(*SpaceID).SpaceID
-	return nil
-}
-
-func (t *SpaceID) MarshalJSON() ([]byte, error) {
-	return []byte(t.String()), nil
-}
diff --git a/id/user.go b/id/user.go
index 6ea9ea52..1abaa0df 100644
--- a/id/user.go
+++ b/id/user.go
@@ -1,9 +1,5 @@
 package id
 
-import (
-	jsoniter "github.com/json-iterator/go"
-)
-
 const (
 	User        = "user"
 	UsersPrefix = "users"
@@ -46,20 +42,3 @@ func parseUserID(parts []string) (*UserID, error) {
 	id.UserID = parts[1]
 	return &id, nil
 }
-
-func (t *UserID) UnmarshalJSON(b []byte) error {
-	var data string
-	if err := jsoniter.Unmarshal(b, &data); err != nil {
-		return err
-	}
-	knownID, err := Parse(data)
-	if err != nil {
-		return err
-	}
-	t.UserID = knownID.(*UserID).UserID
-	return nil
-}
-
-func (t *UserID) MarshalJSON() ([]byte, error) {
-	return []byte(t.String()), nil
-}
-- 
GitLab