Repository: hashicorp/terraform (Go)

Issue:
Config generation wraps numbers and booleans in jsonencode
### Terraform Version

```shell
HEAD
```


### Terraform Configuration Files

```terraform
import {
  to = test_resource.foo
  id = "someresourceid"
}
```


### Debug Output

N/A

### Expected Behavior

When running with `-generate-config-out=generate.tf`, if the returned resource has is a string type, but contains a number or a bool, the output attribute should be a string. e.g.

```terraform
resource "test_resource" "foo" {
  some_string_attribute = "1234"
}
```

### Actual Behavior

```terraform
resource "test_resource" "foo" {
  some_string_attribute = jsonencode(1234)
}
```

### Steps to Reproduce

Create an `import` block for a resource with a string attribute, but with a value that is a primitive, deserializable json type (number or bool) and run ` terraform plan -generate-config-out=generated.tf` 

### Additional Context

I have a fix for this. I am just opening the issue for posterity

### References

_No response_


Discussion:
Thanks for filing this in conjunction with the pull request!
I'm going to lock this issue because it has been closed for _30 days_ ⏳. This helps our maintainers find and focus on the active issues.
If you have found a problem that seems similar to this, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further.



Patch:
diff --git a/internal/genconfig/generate_config.go b/internal/genconfig/generate_config.go
index 5843c88b3e37..87507048b94e 100644
--- a/internal/genconfig/generate_config.go
+++ b/internal/genconfig/generate_config.go
@@ -169,8 +169,6 @@ func writeConfigAttributesFromExisting(addr addrs.AbsResourceInstance, buf *stri
 				// If the value is a string storing a JSON value we want to represent it in a terraform native way
 				// and encapsulate it in `jsonencode` as it is the idiomatic representation
 				if val.IsKnown() && !val.IsNull() && val.Type() == cty.String && json.Valid([]byte(val.AsString())) {
-					buf.WriteString("jsonencode(")
-
 					var ctyValue ctyjson.SimpleJSONValue
 					err := ctyValue.UnmarshalJSON([]byte(val.AsString()))
 					if err != nil {
@@ -183,27 +181,25 @@ func writeConfigAttributesFromExisting(addr addrs.AbsResourceInstance, buf *stri
 						continue
 					}
 
-					tok := hclwrite.TokensForValue(ctyValue.Value)
-					if _, err := tok.WriteTo(buf); err != nil {
-						diags = diags.Append(&hcl.Diagnostic{
-							Severity: hcl.DiagWarning,
-							Summary:  "Skipped part of config generation",
-							Detail:   fmt.Sprintf("Could not create attribute %s in %s when generating import configuration. The plan will likely report the missing attribute as being deleted.", name, addr),
-							Extra:    err,
-						})
-						continue
+					// Lone deserializable primitive types are valid json, but should be treated as strings
+					if ctyValue.Type().IsPrimitiveType() {
+						if d := writeTokens(val, buf); d != nil {
+							diags = diags.Append(d)
+							continue
+						}
+					} else {
+						buf.WriteString("jsonencode(")
+
+						if d := writeTokens(ctyValue.Value, buf); d != nil {
+							diags = diags.Append(d)
+							continue
+						}
+
+						buf.WriteString(")")
 					}
-
-					buf.WriteString(")")
 				} else {
-					tok := hclwrite.TokensForValue(val)
-					if _, err := tok.WriteTo(buf); err != nil {
-						diags = diags.Append(&hcl.Diagnostic{
-							Severity: hcl.DiagWarning,
-							Summary:  "Skipped part of config generation",
-							Detail:   fmt.Sprintf("Could not create attribute %s in %s when generating import configuration. The plan will likely report the missing attribute as being deleted.", name, addr),
-							Extra:    err,
-						})
+					if d := writeTokens(val, buf); d != nil {
+						diags = diags.Append(d)
 						continue
 					}
 				}
@@ -215,6 +211,20 @@ func writeConfigAttributesFromExisting(addr addrs.AbsResourceInstance, buf *stri
 	return diags
 }
 
+func writeTokens(val cty.Value, buf *strings.Builder) tfdiags.Diagnostics {
+	var diags tfdiags.Diagnostics
+	tok := hclwrite.TokensForValue(val)
+	if _, err := tok.WriteTo(buf); err != nil {
+		return diags.Append(&hcl.Diagnostic{
+			Severity: hcl.DiagWarning,
+			Summary:  "Skipped part of config generation",
+			Detail:   "Could not create attribute in import configuration. The plan will likely report the missing attribute as being deleted.",
+			Extra:    err,
+		})
+	}
+	return diags
+}
+
 func writeConfigBlocks(addr addrs.AbsResourceInstance, buf *strings.Builder, blocks map[string]*configschema.NestedBlock, indent int) tfdiags.Diagnostics {
 	var diags tfdiags.Diagnostics
 


Test patch:
diff --git a/internal/genconfig/generate_config_test.go b/internal/genconfig/generate_config_test.go
index a1392326773a..87d3fb778f85 100644
--- a/internal/genconfig/generate_config_test.go
+++ b/internal/genconfig/generate_config_test.go
@@ -500,6 +500,48 @@ resource "tfcoremock_simple_resource" "empty" {
 			expected: `
 resource "tfcoremock_simple_resource" "empty" {
   value = jsonencode(["Hello", "World"])
+}`,
+		},
+		"simple_resource_with_json_primitive_strings": {
+			schema: &configschema.Block{
+				Attributes: map[string]*configschema.Attribute{
+					"id": {
+						Type:     cty.String,
+						Computed: true,
+					},
+					"value_string_number": {
+						Type:     cty.String,
+						Optional: true,
+					},
+					"value_string_bool": {
+						Type:     cty.String,
+						Optional: true,
+					},
+				},
+			},
+			addr: addrs.AbsResourceInstance{
+				Module: nil,
+				Resource: addrs.ResourceInstance{
+					Resource: addrs.Resource{
+						Mode: addrs.ManagedResourceMode,
+						Type: "tfcoremock_simple_resource",
+						Name: "empty",
+					},
+					Key: nil,
+				},
+			},
+			provider: addrs.LocalProviderConfig{
+				LocalName: "tfcoremock",
+			},
+			value: cty.ObjectVal(map[string]cty.Value{
+				"id":                  cty.StringVal("D2320658"),
+				"value_string_number": cty.StringVal("42"),
+				"value_string_bool":   cty.StringVal("true"),
+			}),
+			expected: `
+resource "tfcoremock_simple_resource" "empty" {
+  value_string_bool   = "true"
+  value_string_number = "42"
 }`,
 		},
 		"simple_resource_with_malformed_json": {