Add identity fields to Plan struct (#158)

diff --git a/parse_test.go b/parse_test.go
index 79c9a66..725e281 100644
--- a/parse_test.go
+++ b/parse_test.go
@@ -6,7 +6,6 @@
 import (
 	"bytes"
 	"encoding/json"
-	"io/ioutil"
 	"os"
 	"path/filepath"
 	"reflect"
@@ -21,7 +20,7 @@
 const testGoldenSchemasFileName = "schemas.json"
 
 func testParse(t *testing.T, filename string, typ reflect.Type) {
-	entries, err := ioutil.ReadDir(testFixtureDir)
+	entries, err := os.ReadDir(testFixtureDir)
 	if err != nil {
 		t.Fatalf("err: %s", err)
 	}
@@ -32,7 +31,7 @@
 		}
 
 		t.Run(e.Name(), func(t *testing.T) {
-			expected, err := ioutil.ReadFile(filepath.Join(testFixtureDir, e.Name(), filename))
+			expected, err := os.ReadFile(filepath.Join(testFixtureDir, e.Name(), filename))
 			if err != nil {
 				if os.IsNotExist(err) {
 					t.Skip(err.Error())
diff --git a/plan.go b/plan.go
index d861898..f60739c 100644
--- a/plan.go
+++ b/plan.go
@@ -266,6 +266,11 @@
 	// is either an integer pointing to a child of a set/list, or a string
 	// pointing to the child of a map, object, or block.
 	ReplacePaths []interface{} `json:"replace_paths,omitempty"`
+
+	// BeforeIdentity and AfterIdentity are representations of the resource
+	// identity value both before and after the action.
+	BeforeIdentity interface{} `json:"before_identity,omitempty"`
+	AfterIdentity  interface{} `json:"after_identity,omitempty"`
 }
 
 // Importing is a nested object for the resource import metadata.
@@ -273,6 +278,16 @@
 	// The original ID of this resource used to target it as part of planned
 	// import operation.
 	ID string `json:"id,omitempty"`
+
+	// Unknown indicates the ID or identity was unknown at the time of
+	// planning. This would have led to the overall change being deferred, as
+	// such this should only be true when processing changes from the deferred
+	// changes list.
+	Unknown bool `json:"unknown,omitempty"`
+
+	// The identity can be used instead of the ID to target the resource as part
+	// of the planned import operation.
+	Identity interface{} `json:"identity,omitempty"`
 }
 
 // PlanVariable is a top-level variable in the Terraform plan.
diff --git a/plan_test.go b/plan_test.go
index 1f59fc1..c97f8f9 100644
--- a/plan_test.go
+++ b/plan_test.go
@@ -13,19 +13,34 @@
 )
 
 func TestPlanValidate(t *testing.T) {
-	f, err := os.Open("testdata/basic/plan.json")
-	if err != nil {
-		t.Fatal(err)
-	}
-	defer f.Close()
-
-	var plan *Plan
-	if err := json.NewDecoder(f).Decode(&plan); err != nil {
-		t.Fatal(err)
+	cases := map[string]struct {
+		planPath string
+	}{
+		"basic plan": {
+			planPath: "testdata/basic/plan.json",
+		},
+		"plan with identity": {
+			planPath: "testdata/identity/plan.json",
+		},
 	}
 
-	if err := plan.Validate(); err != nil {
-		t.Fatal(err)
+	for tn, tc := range cases {
+		t.Run(tn, func(t *testing.T) {
+			f, err := os.Open(tc.planPath)
+			if err != nil {
+				t.Fatal(err)
+			}
+			defer f.Close()
+
+			var plan *Plan
+			if err := json.NewDecoder(f).Decode(&plan); err != nil {
+				t.Fatal(err)
+			}
+
+			if err := plan.Validate(); err != nil {
+				t.Fatal(err)
+			}
+		})
 	}
 }
 
diff --git a/testdata/identity/plan.json b/testdata/identity/plan.json
new file mode 100644
index 0000000..ba7b4b6
--- /dev/null
+++ b/testdata/identity/plan.json
@@ -0,0 +1 @@
+{"format_version":"1.2","terraform_version":"1.13.0-dev","planned_values":{"root_module":{"resources":[{"address":"corner_user_identity.user","mode":"managed","type":"corner_user_identity","name":"user","provider_name":"registry.terraform.io/hashicorp/corner","schema_version":0,"values":{"age":999,"email":"a@example.com","id":"a@example.com","name":"test"},"sensitive_values":{},"identity_schema_version":1,"identity":{"email":"a@example.com"}}]}},"resource_changes":[{"address":"corner_user_identity.user","mode":"managed","type":"corner_user_identity","name":"user","provider_name":"registry.terraform.io/hashicorp/corner","change":{"actions":["update"],"before":{"age":null,"email":"a@example.com","id":"a@example.com","name":null},"after":{"age":999,"email":"a@example.com","id":"a@example.com","name":"test"},"after_unknown":{},"before_sensitive":{},"after_sensitive":{},"importing":{"identity":{"email":"a@example.com"}},"before_identity":{"email":"a@example.com"},"after_identity":{"email":"a@example.com"}}}],"prior_state":{"format_version":"1.0","terraform_version":"1.13.0","values":{"root_module":{"resources":[{"address":"corner_user_identity.user","mode":"managed","type":"corner_user_identity","name":"user","provider_name":"registry.terraform.io/hashicorp/corner","schema_version":0,"values":{"age":null,"email":"a@example.com","id":"a@example.com","name":null},"sensitive_values":{},"identity_schema_version":1,"identity":{"email":"a@example.com"}}]}}},"configuration":{"provider_config":{"corner":{"name":"corner","full_name":"registry.terraform.io/hashicorp/corner"}},"root_module":{"resources":[{"address":"corner_user_identity.user","mode":"managed","type":"corner_user_identity","name":"user","provider_config_key":"corner","expressions":{"age":{"constant_value":999},"email":{"constant_value":"a@example.com"},"name":{"constant_value":"test"}},"schema_version":0}]}},"timestamp":"2025-04-30T11:34:17Z"}