2

I'm building a GraphQL query to return back an item and its fields. One field is NameValueList - I can just return it as a string and cast it to an interface

the layout service returns it like this:

"myNameValueList": {
  "value": "key1=1&key2=0"
}

My interface looks like this:

interface MyFields {
  id: string
  name: string
  myNameValueList: string
}

Is there a way I can return it that's not like a query parameter? is there a way I can use nextjs field to map this instead of a string? so it ends up being something like:

interface MyFields {
  id: string
  name: string
  myNameValueList: { [key: string]: string }
}

Thanks in advance

2 Answers 2

1

NameValueList Field, stores value in the form of querystring which gets delivered as it is in layout service. So, in order to get the data in a more meaningful structure you can customize the Field Serializer for NameValueField.

The first step is to create a custom serializer by inheriting Sitecore.LayoutService.Serialization.FieldSerializers.BaseFieldSerializer and overriding WriteValue Method:

public class NameValueListSerializer : BaseFieldSerializer
{
    public NameValueListSerializer(IFieldRenderer fieldRenderer) : base(fieldRenderer)
    {
    }
    protected override void WriteValue(Field field, JsonTextWriter writer)
    {
        Assert.ArgumentNotNull((object)field, nameof(field));
        Assert.ArgumentNotNull((object)writer, nameof(writer));
        try
        {
            writer.WriteStartObject();
            string range = field.Value;
            if (!string.IsNullOrEmpty(range))
            {
                string[] ranges = range.Split('&');
                if (ranges != null)
                {
                    foreach (string dropdownpair in ranges)
                    {
                        string[] pair = dropdownpair.Split('=');
                        writer.WritePropertyName(pair[0]);
                        writer.WriteValue(HttpUtility.UrlDecode(pair[1]));
                    }
                }
            }
            writer.WriteEndObject();
        }
        catch (Exception ex)
        {
            Sitecore.Diagnostics.Log.Error(ex.Message, typeof(NameValueListSerializer));
        }
    }
}

Now, implement the class by inheriting Sitecore.LayoutService.Serialization.Pipelines.GetFieldSerializer.BaseGetFieldSerializer and overriding SetResult Method:

public class GetNameValueListSerializer : BaseGetFieldSerializer
{
   public GetNameValueListSerializer(IFieldRenderer fieldRenderer) : base(fieldRenderer)
   {
   }
   protected override void SetResult(GetFieldSerializerPipelineArgs args)
   {
     args.Result = (IFieldSerializer)new NameValueListSerializer(this.FieldRenderer);
   }
}

Now, the last step is to patch our custom resolver and we need to make sure that we patch it before GetDefaultFieldSerializer processor:

<?xml version="1.0" encoding="utf-8" ?>
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
  <sitecore>
    <pipelines>
      <group groupName="layoutService">
        <pipelines>
          <getFieldSerializer>
            <processor patch:before="processor[@type='Sitecore.LayoutService.Serialization.Pipelines.GetFieldSerializer.GetDefaultFieldSerializer, Sitecore.LayoutService']" type="Sandbox.GetNameValueListSerializer, Sandbox" resolve="true">
              <FieldTypes hint="list">
                <fieldType id="1">name value list</fieldType>
              </FieldTypes>
            </processor>
          </getFieldSerializer>
        </pipelines>
      </group>
    </pipelines>
  </sitecore>
</configuration>

Now, instead of the querystring we will get the object of key-value pairs.

Credit: https://gauravarorasb.medium.com/sitecore-headless-services-custom-field-serializer-for-namevaluelist-field-da2b51280cd7

Hope it helps!

2
  • your answer looks like an exact copy of gauravarorasb.medium.com/… . You should clearly state at the beginning that it's not your code and link to the original article. Otherwise it's a plagiarism and that's not welcome on Sitecore Stack Exchange.
    – Marek Musielak
    Nov 21, 2023 at 7:02
  • Thanks, @MarekMusielak. I do try to always add credit/reference links to the original author of the article. I did miss this time. I'll update the answer. Nov 21, 2023 at 7:11
1

solution by Sumit was great but just posting an alternative solution for those who want to do it in typescript rather than adding a custom field serializer:

function getValues(myValue: string) {
  const myValueStringArray = myValue.split('&')
  const myObj: { [key: string]: number } = {}
  myValueStringArray .forEach((pair) => {
    const [key, value] = pair.split('=')
    const parsedValue = parseInt(value)
    if (!isNaN(parsedValue)) {
      myObj[key] = parsedValue
    }
  })
  return myObj
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.